Open dev590t opened 3 years ago
This is not a good idea. The best practise is to have encoder/decoder in the compaign object.
case class A(v: Int)
object A {
implicit val encoder: JsonEncoder[A] = DeriveJsonEncoder.gen[A]
}
case class B(v: A)
object B {
implicit val encoder: JsonEncoder[B] = DeriveJsonEncoder.gen[B]
}
B(A(1)).toJson
Otherwise just simple add the derivation of A before B
case class A(v: Int)
case class B(v: A)
object B {
implicit val encoder: JsonEncoder[A] = DeriveJsonEncoder.gen[A]
implicit val encoder: JsonEncoder[B] = DeriveJsonEncoder.gen[B]
}
B(A(1)).toJson
@aparo
The best practise is to have encoder/decoder in the compaign object.
However, I feel this solution is heavy. Especially, if we have many case class in the program. We should spend many time for the preparation before use zio json. Finally, the developer will write a mini program to collect all name of case class, and generate the code of encoder/decoder.
Maybe it is possible to add such mini program in the project? The program analyze the scala code, return the struct of a case class(with all dependant case class), and generate the code of of all encoder/decoder.
zio-json is inspired from jsoniter-scala. But I have tested jsoniter-scala. It can generate encoder for nested case class:
{
case class Device(id: Int, model: String)
case class User(name: String, devices: Seq[Device])
val userObject =
(User(name = "John", devices = Seq(Device(id = 2, model = "iPhone X"))))
suite("generate encoder for nested case class")(
test("jsoniter-scala") {
import com.github.plokhotnyuk.jsoniter_scala.macros._
import com.github.plokhotnyuk.jsoniter_scala.core._
implicit val codec: JsonValueCodec[User] = JsonCodecMaker.make
val user = readFromArray(
"""{"name":"John","devices":[{"id":1,"model":"HTC One X"}]}"""
.getBytes("UTF-8")
)
val json = writeToArray(userObject)
assert(1)(equalTo(1))
},
test("zio-json") {
import zio.json._
implicit val encoder: JsonEncoder[User] = DeriveJsonEncoder.gen[User]
// magnolia: could not find JsonEncoder.Typeclass for type Seq[Device]
// [error] in parameter 'devices' of product type User
// [error] implicit val encoder: JsonEncoder[User] = DeriveJsonEncoder.gen[User]
userObject.toJson
assert(1)(equalTo(1))
}
)
}
This code produce a compilation error for zio-json, no for jsoniter-scala.
I don't know how jsoniter-scala is implemented. Maybe it is possible to take idea from it?
Good idea! in my current microservices I had to resign from zio-json due to many nested case classes. Its very inconvenient to write 20 decoders/encoders just to operate on 1 case class.
@fsvehla I think we should close this issue as it's never a good idea to provide automagic instances.
If people think it's too verbose, they should use the @jsonDerive
macro.
See https://zio.dev/zio-json/configuration#jsonderive
zio json can't generate encoder for nested case class:
It is possible bypass the issue with
sealed trait
. But often, we can't change the case class defined in library. We haven't other solution that define encoder/decoder for all case class.Is it possible to use scala macro to auto generate encoder of all nested case class?