代码之家  ›  专栏  ›  技术社区  ›  crowgers

Scala—使用映射和列表的嵌套结构处理JSON

  •  1
  • crowgers  · 技术社区  · 6 年前

    Api请求 返回a Json字符串 如下所示。我一直在努力 Scala中的解析 ,添加 “名称” 字段设置为列表,然后使用其他列表筛选此列表。这个 API来自第三方 因此无法修改格式。

    示例列表(此处的值中有2个条目,但最多可以有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. 如何访问对象内映射的嵌套元素(Any,Any)?
    2. 这是反序列化JSON字符串的正确方法吗?

    非常感谢您的帮助!

    1 回复  |  直到 6 年前
        1
  •  4
  •   retrospectacus    6 年前

    在Scala中,您应该总是喜欢有用的类型,而不是 Any 。不要将JSON解析为 Map[String, Any] -围绕Api结果数据结构设计案例类,并将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"))
      }
    }