JsonIter Scala - Format macro

Viewed 86

In Play Json you can use this macro Jsonx.formatInline for example, which inlines the json object to its json property. Is there any approach to achieve this using jsoniter library? For instance, in this code:

case class Foo(values : String)
case class WrapperOfFoo(val : rapperOfFoo)
val codec : JsonValueCodec[[WrapperOfFoo]] = JsonCodecMaker.make
val messageFoo = new Foo("test")
val message = new WrapperOfFoo(messageFoo)
val json = writeToArray(message)(codec).map(_.toChar).mkString
println(json)

The result is:

{
  "val": {
    "values": "test"
  }
}

Desired output:

{
  "val" : "test"
}

Since it's just a wrapper that has only one property, I want it to be inlined, is there a way to achieve this in JsonIter?

1 Answers

As a complement to my comment (about the implicit class), this is kind of what I meant:

implicit class CodecOps[A](codec: JsonValueCodec[A]) {
    def encodeBy[B](mapFunc: A => B)(implicit bCodec: JsonValueCodec[B]): JsonValueCodec[A] =
      new JsonValueCodec[A] {
        override def decodeValue(in: JsonReader, default: A): A = codec.decodeValue(in, default)

        override def encodeValue(x: A, out: JsonWriter): Unit =
          bCodec.encodeValue(mapFunc(x), out)

        override def nullValue: A = codec.nullValue
      }

    def decodedBy[B](contraMapFunc: B => A)(implicit bCodec: JsonValueCodec[B]): JsonValueCodec[A] =
      new JsonValueCodec[A] {
        override def decodeValue(in: JsonReader, default: A): A =
          contraMapFunc(bCodec.decodeValue(in, bCodec.nullValue))

        override def encodeValue(x: A, out: JsonWriter): Unit = codec.encodeValue(x, out)

        override def nullValue: A = codec.nullValue
      }
  }

// And then inside your models, assuming implicit JsonValueCodec[Foo] is defined earlier
implicit val codec : JsonValueCodec[FooWrapper] = JsonCodecMaker.make[FooWrapper]
    .encodeBy(_.foo)
    .decodedBy(FooWrapper.apply)
    

println(json)
// result => {"values":"test"}
println(readFromString[FooWrapper]("{\"values\":\"test\"}"))
// result => FooWrapper(Foo(test))

Note that this is the same behavior in Jsonx.formatInline, so it doesn't return {"value": "test"}. Imagine this way, what happens if Foo was a complex structure? what key should value get replaced with?

Related