Scala - 使用嵌套的地图和列表结构处理JSON

时间:2018-04-11 15:24:08

标签: json scala unmarshalling

Api请求会返回如下所示的 Json字符串。我一直在尝试在Scala中解析,将“name”字段添加到列表中,然后使用其他列表过滤此列表。 API来自第三方,因此无法修改格式。

示例列表(此处有两个值,但最多可以有300个):

{
    "size": 20,
    "values": [{
            "name": "mullock",
            "upstatus": "Green",
            "details": {
                "key": "rupture farms",
                "server": "mudos",
                "owner": "magog_cartel",
                "type": "NORMAL",
                "links": {
                    "self": [{
                        "address": "https://mudos.com:port/access"
                    }]
                }
            }
        },
        {
            "name": "tassadar",
            "upstatus": "Orange",
            "details": {
                "key": "archon",
                "server": "protoss",
                "owner": "aspp67",
                "type": "NORMAL",
                "links": {
                    "self": [{
                        "address": "https://aiur.com:port/access"
                    }]
                }
            }
        }
    ],
    "limit": 100
}

我尝试使用jackson和一些建议的函数(下面)解组字符串,这些函数在应用程序的其他部分中使用但我不完全理解。

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper

object Json {
    /* Json/Scala translation utilities
     */
    val mapper = {
        val _mapper = new ObjectMapper() with ScalaObjectMapper
        _mapper.registerModule(DefaultScalaModule)
        _mapper
    }

    def dump(obj: Any): String = {
        mapper.writeValueAsString(obj)
    }

    def dumpObj(fields: (Any, Any)*): String = {
        dump(fields.toMap)
    }

    def read[T: Manifest](content: String): T = {
        mapper.readValue(content, mapper.constructType[T])
    }

    def readObj(content: String): Map[Any, Any] = {
        return read[Map[Any, Any]](content)
    }

}
  1. 如何访问对象Map(Any,Any)中的嵌套元素?
  2. 这是反序列化JSON字符串的正确方法吗?
  3. 任何帮助非常感谢!

1 个答案:

答案 0 :(得分:1)

在Scala中,您应该始终使用Any之上的有用类型。不要将JSON解析为Map[String, Any] - 围绕Api Result数据结构的设计案例类,并将JSON读入该类:

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper

case class ApiResult(size: Int, limit: Int, values: Seq[Entity])
case class Entity(name: String, upstatus: String, details: EntityDetails)
case class EntityDetails(key: String, server: String, owner: String, `type`: String, links: EntityLinks)
case class EntityLinks(self: Seq[EntityLinkAddress])
case class EntityLinkAddress(address: String)

object Foo {
  val mapper = new ObjectMapper() with ScalaObjectMapper
  mapper.registerModule(DefaultScalaModule)

  def test(): Unit = {
    val json: String =
      """
        |{
        |    "size": 20,
        |    "values": [{
        |            "name": "mullock",
        |            "upstatus": "Green",
        |            "details": {
        |                "key": "rupture farms",
        |                "server": "mudos",
        |                "owner": "magog_cartel",
        |                "type": "NORMAL",
        |                "links": {
        |                    "self": [{
        |                        "address": "https://mudos.com:port/access"
        |                    }]
        |                }
        |            }
        |        },
        |        {
        |            "name": "tassadar",
        |            "upstatus": "Orange",
        |            "details": {
        |                "key": "archon",
        |                "server": "protoss",
        |                "owner": "aspp67",
        |                "type": "NORMAL",
        |                "links": {
        |                    "self": [{
        |                        "address": "https://aiur.com:port/access"
        |                    }]
        |                }
        |            }
        |        }
        |    ],
        |    "limit": 100
        |}
        |""".stripMargin

    val r = mapper.readValue[ApiResult](json)

    println(r.values.find(_.name == "tassadar"))
  }
}