Codec does not work with N1QL + SDK + case classes

I used Scala SDK’s upsert method to create/persist 2 documents into the databse, using case classes. I used the same case classes on couchbase website. Following are the records in the database (meta().id = name):
{"name":"user1","age":21,"addresses":[{"line1":"address1"},{"line1":"address2"}]}
{"name":"user2","age":21,"addresses":[{"line1":"address1"},{"line1":"address2"}]}

After that I tried to retrieve the records with SDK N1QL (which worked fine) and convert them to User case class. However, this faced the following error (it seems the decoder is not applied to the result properly. Note that I do not face this issue if I use JsonObject instead of case classes. I also do not face the issue if I use get method to retrieve a single doc.):

Error: com.github.plokhotnyuk.jsoniter_scala.core.JsonParseException: missing required field "name", offset: 0x0000005d, buf:
           +-------------------------------------------------+
           |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+----------+-------------------------------------------------+------------------+
| 00000030 | 3a 5b 7b 22 6c 69 6e 65 31 22 3a 22 61 64 64 72 | :[{"line1":"addr |
| 00000040 | 65 73 73 31 22 7d 2c 7b 22 6c 69 6e 65 31 22 3a | ess1"},{"line1": |
| 00000050 | 22 61 64 64 72 65 73 73 32 22 7d 5d 7d 7d       | "address2"}]}}   |
+----------+-------------------------------------------------+------------------+

Following is the code I used to retrieve the records from the database.

  case class Address(line1: String)
  case class User(name: String, age: Int, addresses: Seq[Address])
  object User {
    implicit val codec: Codec[User] = Codecs.codec[User]
  }

  val statement = """select * from MyDbName where meta().id like 'user%';"""

  val cluster = Cluster.connect(context.host, context.user, context.password) // context contains the db connection info.
  val bucket = cluster.bucket(context.bucket)
  cluster.query(statement)
    .flatMap(_.allRowsAs[User]) match {
    case Success(rows: Seq[User]) =>
      rows.foreach(row => println(row))
    case Failure(err) =>
      println(s"Error: $err")
  }

Thanks!
Ali

PS: I am using "scala-client 1.0.0-alpha.6" and Couchbase-server community 6.0.0 on Windows 10 .

1 Like

Hey @ali.parsaei

Thanks for the excellent bug report, that contained everything I needed to replicate the issue, and I’ve created Loading... for it.

This is alpha software of course and still has a few rough areas, especially around parts such as a decoding/encoding case classes directly that are very new. Thank you for your patience as we iron out the kinks :slight_smile:

1 Like

Hey @ali.parsaei

Actually on further investigation, this isn’t a bug - it’s just how the N1QL service works - and the query just needs a little tweaking. Please see the ticket for how to do so.

Hey @graham.pople
Thanks for the solution.
I’d appreciate it if you modify the following statement on Query | Couchbase Docs for case classes:

val statement = “”“select * from <dbname> limit 10;”“”

@ali.parsaei good idea. I’ve just pushed a changeset to the docs so this should go live soon-ish.

1 Like