使用Scala提取嵌套的JSON元素

4

我有以下的Scala代码。我的目标是在不知道键有多少个和有多深的情况下提取键的值。


    import org.json4s.jackson.JsonMethods._
    import org.json4s.{DefaultFormats, JField, JObject, JString, JValue}

    object jsonLift {

        implicit val formats = DefaultFormats

        val js = parse(
            """
    {
      "url": "imap.yahoo.com",
        "credentials": {
        "username": "myusername",
        "password": "mypassword"
         },
        "some key":{
            "other key": {
                "username": "hello"
            }
        }
    }
            """)


            def getElem(elem: String, json:JValue) = for {
                    JObject(child) <- json
                    JField(elem, JString(value)) <- child       // this does not return the expected result
    //              JField("username", JString(value)) <- child // this returns the expected result
                } yield  value


        def main(args: Array[String]) {

            val result = getElem("username", js)
            println(result)

        }
    }

上述代码的结果是List(imap.yahoo.com, myusername, mypassword, hello),这不是我期望的结果。我的预期结果是List(myusername, hello)
然而,如果我直接在getElem方法中更改变量elem为我感兴趣的键(例如:"username"),我将获得预期的结果:List(myusername, hello),它们都是键"username"的值。
如何通过调用带有JSON键名称作为参数的getElem方法来获取预期的值列表?例如:getElem("JSON key", json) 谢谢!

预期结果应该是 List(myusername, hello) - geo
2个回答

3

getElem更改为

def getElem(elem: String, json:JValue) = for {
  JObject(child) <- json
  JField(`elem`, JString(value)) <- child
} yield  value

如果在 RHS 中没有使用反引号将 elem 包含起来,你就会将 type JField = (String, JValue) 的第一个元素绑定到一个新的名称 elem 上,并遮蔽方法参数 elem


我不知道使用反引号会像这样匹配。好知道了,谢谢! - Mike Curry
我也不知道。看起来像是 Scala 风格的解决方案。谢谢!确实返回了预期的结果。 - geo

1
所以,在这里问题是当你使用:

JField(elem, JString(value)) <- child 

在你的for推导式中,这个新定义的elem遮盖了你传递给getElem方法的elem

我猜你的意图是,如果传递给getElem的值elemJField的名称相同,则会匹配。然而实际上,符号elem绑定到键名。

你可以通过对上面的行进行小的改动来实现你想要的效果,如下所示:

JField(key, JString(value)) <- child if key == elem

只有当JField的名称与elem匹配时,才会将值绑定到value


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接