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?