Set up
I have an enumeration defined using sealed trait
, and a custom serializer for it:
import org.json4s.CustomSerializer
import org.json4s.JsonAST.JString
import org.json4s.DefaultFormats
import org.json4s.jackson.Serialization
sealed trait Foo
case object X extends Foo
case object Y extends Foo
object FooSerializer
extends CustomSerializer[Foo](
_ =>
({
case JString("x") => X
case JString("y") => Y
}, {
case X => JString("x")
case Y => JString("y")
})
)
This is great, and works well when added to the formats:
{
implicit val formats = DefaultFormats + FooSerializer
Serialization.write(X) // "x"
}
This is great!
Problem
If the serializer is not added to the formats, json4s will use reflection to create a default representation of the fields, which is extremely unhelpful for these object
s that don't have fields. It does this silently, seemingly without a way to control it.
{
implicit val formats = DefaultFormats
Serialization.write(X) // {}
}
This is a problematic, as there's no indication of what's gone wrong until much later. This invalid/useless data might be sent around the network or written to databases, if tests don't happen to catch it. And, this may be exposed publicly from a library, meaning downstream users have to remember it as well.
NB. this is different to read
, which throws an exception on failure, since the Foo
trait doesn't have any useful constructors:
{
implicit val formats = DefaultFormats
Serialization.read[Foo]("\"x\"")
}
org.json4s.package$MappingException: No constructor for type Foo, JString(x)
at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$constructor(Extraction.scala:417)
at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$instantiate(Extraction.scala:468)
at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$result$6.apply(Extraction.scala:515)
...
Question
Is there a way to either disable the default {}
formatting for these objects, or to "bake" in the formatting to the object itself?
For instance, having write
throw an exception like read
would be fine, as it would flag the problem to the caller immediately.
Aucun commentaire:
Enregistrer un commentaire