如何通过路径从JSONObject中获取嵌套值?

8
我将尝试实现一个函数,该函数接受任意的JSONObject和一个路径String,并返回与该路径对应的对象属性。
例如,给定以下json:
{
"name": "John", 
"friends": [
  {"name": "Paul",
   "age":42},
  {"name": "Peter",
   "age":24}
 ],
"address": {"city": "London"}
}
  • getAttribute(jsonObject, "name") 应该返回 "John"
  • getAttribute(jsonObject, "address.city") 应该返回 "London"
  • getAttribute(jsonObject, "friends[0].name") 应该返回 "Paul"

请注意,此JSON仅为示例,jsonObject没有预定义的结构,可以表示任何有效的json。

我编写了第一个版本来实现前两个案例,但处理数组和多层数组 "foo [0] [0] .bar" 会给这个函数带来很多复杂性。

是否有推荐的工具/库/方法可根据“复杂”路径从JSONObject获取属性?


不是... 有很多库.. Gson,Jackson等 - ΦXocę 웃 Пepeúpa ツ
1
请使用GSON而不是从路径获取值,这里您将直接从实体类对象中获取值。 - Amrut Bidri
1
@ΦXocę웃Пepeúpaツ:我知道这些库存在,但我找不到如何使用它们从任意JSONObject中获取属性。如果您知道如何做,请随时回答问题! - PLNech
1
@AmrutBidri:我无法创建类对象,因为JSON会动态变化。似乎GSON没有提供解决方案来获取给定此类json路径的属性,但如果我错了,请告诉我! - PLNech
1
@RajeshKushvaha:请告诉我,当JSON结构在每个调用中都不同的情况下,我该如何使用POJOs。 - PLNech
显示剩余7条评论
6个回答

5
JSONPath标准由Stefan Goessner撰写,涵盖了更复杂的语法,但也处理了“经典JavaScript” JSON路径语法。
使用JayWay的Java实现,回答这个问题是微不足道的。
public String getAttribute(JSONObject json, String path) {
    return JsonPath.read(json.toString(), path);
}

3

1
谢谢!虽然你链接的问题与我的稍有不同,但是第一个答案暗示了我可以使用 Jackson 来解决。关于 JSONPath,我考虑过它,但它的语法似乎涵盖了比在 JavaScript 中使用的 "传统" json 路径更多的内容,我担心可能会出现解析这些路径的潜在问题。 - PLNech
1
没问题:)。希望能有所帮助。 - rares.urdea
最终,JSONPath是最好的选择,再次感谢! :) - PLNech
很高兴它有用! - rares.urdea

1
以下本地代码可能对您有所帮助,
function getDeepValue (object, path, defaultValue) {
    let pathTokens = path.split('.')
    let v = object
    for(let p of pathTokens) {
        try {
            v = Object.prototype.hasOwnProperty.call(v,p)?v[p]:defaultValue
        } catch (catchedError) {
            v = defaultValue
            break
        }
    }
    return v
}


let o = {
    a: {
        b: {
            1:{
                x:9
            },
            c: [{x:1},{x:2}]
        }
    }
}

let path = 'a.b.c.1.x'
console.log(getDeepValue(o, path)) // prints 2

1
谢谢你的建议!不过,这并不能涵盖数组引用语法("a.b[0].c")的情况,但如果有人想从头实现这个功能,这可能是一个很好的起点。 - PLNech

1
我如何解决这个问题:
  import io.restassured.path.json.JsonPath;


String  id = JsonPath.given(Myobject).get(path).toString();

使用这个库的好处是,即使你的路径中包含数组,它也可以处理。
例如:String path="Myobject[0].id"

0
在2022年,使用Kotlin,您可以添加以下扩展。
fun JSONObject.getFromPath(path: String, separator: String = ".") =
    path.split(separator).fold(this) { obj, name -> obj.getJSONObject(name)}

-1

你可以使用GSON库将你的JSON字符串解析成POJO类。

private final static Gson GSON = new GsonBuilder().create();

public static <T> T fromJSON(String json, Class<T> clazz) {
    try {
        return GSON.fromJson(json, clazz);
    } catch (JsonSyntaxException e) {
        LOGGER.warn("Could not deserialize object", e);
    }
    return null;
}

根据你的JSON结构设计你的模型类。


2
谢谢,但是由于没有预定义的结构,我无法创建与之匹配的类。我唯一能做的假设就是对象将是有效的JSON。 - PLNech
2
因为正如我的评论所解释的那样,这并不能回答问题:我无法创建一个POJO类,因为JSONObject每次都会表示不同的JSON结构。 - PLNech

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