【问题标题】:How can I parse a json and extract to different case classes depending of its content如何解析 json 并根据其内容提取到不同的案例类
【发布时间】:2014-11-10 10:24:38
【问题描述】:

我正在尝试使用 json4s 以 json 格式解析不同类型的事件。我编写了一些案例类来表示所有继承自基类Event 的不同事件:

  abstract class Event{ def EventType : String }
  case class StartSession(val EventType: String, val Platform: String) extends Event
  case class AdView(val EventType: String, val EventSubtype: String) extends Event

这是我用来解析StartSession事件的函数:

  def parser(json: String): Event = {
    val parsedJson = parse(json)
    val s = parsedJson.extract[StartSession]
    return s
  }

这个函数会正确解析像{"EventType":"StartSession","Platform":"Portal"}这样的json

我正在寻找一种方法来概括解析器函数,以便我可以使用它来解析从Event 继承的所有类型的事件,然后对函数的返回值进行模式匹配。

【问题讨论】:

    标签: scala json4s


    【解决方案1】:

    类型提示提供了问题的解决方案。如果你有一个多态类型,比如Event,类型提示(这里是EventType)告诉json4s一个json对象应该被反序列化成哪个实际类型。

    作为参考,请查看github page of json4s。有一个部分叫做“Serializing polymorphic Lists”。

    由于类型提示只需要反序列化,我们可以去掉Event中的字段EventType

    abstract class Event
    case class StartSession(Platform: String) extends Event
    case class AdView(EventSubtype: String) extends Event
    

    我们需要将Formats 实例带入extract 的范围内。实例告诉 json4s 如何进行反序列化。在我们的例子中,我们需要专门化 typeHintFieldNametypeHints。第一个是我们类型提示的键,在示例中是"EventType"。后者是从字符串值到类的映射。如果我们使用类名作为值,那么ShortTypeHints 就可以了。否则,我们可以实现我们自己的专业TypeHints

    具体的解决方案如下:

    def main(args: Array[String]): Unit ={
      val json =
        s"""
           |[
           |  {
           |    "EventType": "StartSession",
           |    "Platform": "Portal"
           |  },
           |  {
           |    "EventType": "AdView",
           |    "EventSubtype": "SpecializedView"
           |  }
           |]
         """.stripMargin
      implicit val formats = new DefaultFormats {
        override val typeHintFieldName: String = "EventType"
        override val typeHints: TypeHints =
          ShortTypeHints(
            List(classOf[StartSession], classOf[AdView])
          )
      }
      val parsedJson = parse(json)
      val s = parsedJson.extract[List[Event]]
      println(s)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2018-05-14
      • 2014-06-27
      • 1970-01-01
      相关资源
      最近更新 更多