【问题标题】:Deserialization of case object in Scala with JSON4S使用 JSON4S 反序列化 Scala 中的案例对象
【发布时间】:2016-01-13 03:58:23
【问题描述】:

我有一些案例类定义如下:

sealed trait Breed
case object Beagle extends Breed
case object Mastiff extends Breed
case object Yorkie extends Breed

case class Dog(name: String, breed: Breed)

我还有一个用 Scalatra 定义的端点:

post("/dog") {
  val dog = parsedBody.extract[Dog]
  ...
}

我想要这个 JSON 对象:

{
  name: "Spike",
  breed: "Mastiff"
}

反序列化为Dog 的适当实例。我正在努力弄清楚如何为Breed 编写自定义反序列化程序并将其注册到 JSON4S。

【问题讨论】:

    标签: json scala scalatra json4s


    【解决方案1】:

    你需要像下面这样编写序列化器:

    序列化器

    case object BreedSerializer extends CustomSerializer[Breed](format => (
        {
          case JString(breed) =>  breed match {
            case "Beagle" => Beagle
            case "Mastiff" => Mastiff
            case "Yorkie" => Yorkie
          }
          case JNull => null
        },
        {
          case breed:Breed => JString(breed.getClass.getSimpleName.replace("$",""))
        }))
    

    现在,您必须将此序列化程序添加到默认格式。

    import org.json4s.CustomSerializer
    val serializers = List(BreedSerializer)
    implicit lazy val serializerFormats: Formats = DefaultFormats ++ serializers
    

    希望这能解决您的问题。

    【讨论】:

      【解决方案2】:

      您可以像您提到的那样为Breed 创建一个CustomSerializer

      import org.json4s._
      import org.json4s.JsonDSL._
      import org.json4s.native.JsonMethods._
      import org.json4s.native.Serialization
      import org.json4s.native.Serialization._
      
      object BreedSerializer extends CustomSerializer[Breed]( format => ( 
        {
          case JString("Beagle")  => Beagle
          case JString("Mastiff") => Mastiff
          case JString("Yorkie")  => Yorkie
        }, {
          case Beagle  => JString("Beagle") 
          case Mastiff => JString("Mastiff")
          case Yorkie  => JString("Yorkie")
        }  
      ))
      

      你可以用作:

      val json1 = """{ "name": "Spike", "breed": "Yorkie" }"""
      val json2 = """{ "name": "Pluto", "breed": "Mastiff" }"""
      
      implicit val json4sFormats = Serialization.formats(NoTypeHints) + BreedSerializer
      
      val dog1 = parse(json1).extract[Dog] // Dog(Spike,Yorkie)
      val dog2 = parse(json2).extract[Dog] // Dog(Pluto,Mastiff)
      

      【讨论】: