Scala json4s 密封特征作为枚举

标签 scala enums traits json4s sealed

我们的状态定义为:

sealed trait Status
case object Status {
  case object StatusA extends Status
  case object StatusB extends Status
  case object StatusC extends Status
}

我们的状态如下:
val status = Status.StatusA

有没有办法用预定义的 json4s 来(反)序列化那种结构?格式化者?

我们尝试使用默认的格式化程序,例如:
implicit val formats = new org.json4s.DefaultFormats

它没有用。接下来我们尝试使用 extjson4s 提供使用枚举支持:
implicit val formats = org.json4s.DefaultFormats + new org.json4s.ext.EnumSerializer(Status)

它没有再次工作。我们不得不彻底改变 sealed trait 的结构实际Enumeration s。有什么办法可以用 case class是吗?

最佳答案

这是一个完整的工作示例,我稍微更改了您的类以使示例更简单,这样您就可以以不同的方式使用“名称”,实际上可以省略“定义名称”,但在这种情况下,您需要更改序列化器有点。第二个序列化程序就在下面。



    sealed trait Status {
      def name: String
    }

    case object Status {
      def apply(name: String): Status = name match {
        case StatusA.name => StatusA
        case StatusB.name => StatusB
        case StatusC.name => StatusC
        case _ => throw new UnsupportedOperationException("Unknown value")
      }
    }

    case object StatusA extends Status {
      override val name = "StatusA"
    }

    case object StatusB extends Status {
      override val name = "StatusB"
    }

    case object StatusC extends Status {
      override val name = "StatusC"
    }

    class StatusSerializer extends CustomSerializer[Status](formats =>
      ( {
        case JString(s) => Status(s)
        case JNull => throw new UnsupportedOperationException("No status specified")
      }, {
        case status: Status => JString(status.name)
      })
    )

    case class SimpleRichObject(someString: String, someInt: Int, statuses: List[Status])

    object Test extends App {
      implicit val formats = DefaultFormats + new StatusSerializer
      val obj = SimpleRichObject("Answer to life the universe and everything", 42, List(StatusA, StatusB, StatusC))

      def toCompactJsonString(any: Any) = {
        JsonMethods.compact(JsonMethods.render(Extraction.decompose(any)))
      }

      def toPrettyJsonString(any: Any) = {
        JsonMethods.pretty(JsonMethods.render(Extraction.decompose(any)))
      }

      /** To Json */
      println(s"Compact json:\n${toCompactJsonString(obj)}")
      println(s"Pretty json:\n${toPrettyJsonString(obj)}")

      /** From Json */
      val json =
        """{
          |  "someString":"Here is a another String",
          |  "someInt":1234,
          |  "statuses":["StatusA","StatusB"]
          |}""".stripMargin

      val richObj = JsonMethods.parse(json).extract[SimpleRichObject]
      println(s"Rich object toString: $richObj")
    }


这是第二个序列化程序,通过使用第二个序列化程序,您无需在“枚举”中定义额外的代码


    class SecondStatusSerializer extends CustomSerializer[Status](formats =>
      ( {
        case JString(s) => s match {
          case "StatusA" => StatusA
          case "StatusB" => StatusB
          case "StatusC" => StatusC
        }
        case JNull => throw new UnsupportedOperationException("No status specified")
      }, {
        case status: Status => status match {
          case StatusA => JString("StatusA")
          case StatusB => JString("StatusB")
          case StatusC => JString("StatusC")
        }
      })
    )


这是运行时的外观,紧凑的 json:
{"someString":"Answer to life the universe and everything","someInt":42,"statuses":["StatusA","StatusB","StatusC"]}

漂亮的json:
{
  "someString":"Answer to life the universe and everything",
  "someInt":42,
  "statuses":["StatusA","StatusB","StatusC"]
}

富对象 toString: SimpleRichObject(这里是另一个 String,1234,List(StatusA, StatusB))

关于Scala json4s 密封特征作为枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31135383/

相关文章:

java - Scala Iterator 与 Java Iterator 的问题(类型转换噩梦): How to cast to Java from Scala?

wpf - 将枚举类型绑定(bind)到文本框

python - 无法在 windows、python 上安装 traits

scala - 如何从特征中获取常量值?

python - 如何在 Django 中正确使用 "choices"字段选项

unit-testing - 当 `Result`不是 `Copy`时,设计单元测试

scala - 如何创建所有 Row 值的逗号分隔字符串

scala - 相当于 javascript 运算符 ||在斯卡拉

json - Scala - Spark - 如何将包含一个字符串列的数据帧转换为具有 rigth 类型的列的 DF?

ios - 无法使用 NSKeyedArchiver 保存我的模型