Запечатанная черта Scala json4s как перечисление

Наш статус определяется как:

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 fomratters?

Мы пробовали форматирование по умолчанию, например:

implicit val formats = new org.json4s.DefaultFormats

и это не сработало. Затем мы попытались использовать ext, предоставленный json4s с поддержкой Enum:

implicit val formats = org.json4s.DefaultFormats + new org.json4s.ext.EnumSerializer(Status)

и снова не получилось. Нам пришлось полностью изменить структуру sealed trait на фактические Enumeration. Есть ли способ сделать это с помощью case classes?


person zmeda    schedule 30.06.2015    source источник


Ответы (1)


Вот полный рабочий пример, я немного изменил ваши классы, чтобы упростить пример, и таким образом вы можете использовать «имя» по-разному, вы можете фактически опустить «имя определения», но в этом случае вам нужно будет изменить сериализатор немного. Второй сериализатор чуть ниже.



    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")
    }

Вот второй Serializer, используя второй, вам не нужно определять дополнительный код в ваших «Enums».



    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 (вот еще одна строка, 1234, список (StatusA, StatusB))

person Tal G.    schedule 04.02.2016