Home > database >  JsonIter Scala - Format macro
JsonIter Scala - Format macro

Time:05-29

In play framework - json you can add macro like Jsonx.formatInline for example- which inline json object to json property. If there is way to achieve this jsoniter library? For example :

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)

Real result : { "val" : { "values" : "test" }}

Required result : { "val" : "test" } Due to it got only one property it does inline, can it be achieved with jsoniter?

CodePudding user response:

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