【问题标题】:How can I get a nested value in a JSONObject from its path?如何从其路径中获取 JSONObject 中的嵌套值?
【发布时间】:2017-04-08 13:54:36
【问题描述】:

我正在尝试实现一个函数,给定任何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 获取属性?

【问题讨论】:

  • nope.... 有很多很多库.. Gson、Jackson 等
  • 请使用 GSON 而不是从路径中获取值,这里您将直接从实体类对象中获取值
  • @ΦXocę웃Пepeúpaツ:我知道这些库存在,但我找不到如何使用这些库从任意JSONObject 获取属性。如果您知道该怎么做,请随时回答问题!
  • @AmrutBidri:我无法创建类对象,因为 JSON 会动态变化。似乎GSON 没有提供在给定这样的 json 路径的情况下获取属性的解决方案,但如果我错了,请告诉我!
  • @RajeshKushvaha:请解释一下当 JSON 结构随每次调用而变化时我如何使用 POJO。

标签: java android json parsing


【解决方案1】:

Stefan Goessner 的 JSONPath standard 涵盖了更复杂的语法,但它也处理“经典 javascript”JSON 路径语法。

使用JayWay's implementation for Java,回答问题很简单:

public String getAttribute(JSONObject json, String path) {
    return JsonPath.read(json.toString(), path);
}

【讨论】:

    【解决方案2】:

    如果我正确理解您的问题,您可能已经得到了回答 here

    或者,您也可以尝试以下开源库:

    https://github.com/jayway/JsonPath

    【讨论】:

    • 谢谢!尽管您链接的问题有些不同,但the first answer 暗示了我如何使用杰克逊来解决这个问题。关于 JSONPath,我考虑过它,但它的语法似乎比 javascript 中的“经典”json 路径涵盖的内容要多得多,而且我担心用它解析这些路径时可能会出现问题。
    • 没问题:)。希望对你有帮助
    • 最后 JSONPath 是最好的选择,再次感谢! :)
    • 很高兴它有用!
    【解决方案3】:

    我如何解决问题:

      import io.restassured.path.json.JsonPath;
    
    
    String  id = JsonPath.given(Myobject).get(path).toString();
    

    使用这个库的好处是,即使你的 path 有数组,它也可以处理 那个

    示例:字符串路径="Myobject[0].id"

    【讨论】:

      【解决方案4】:

      以下本机代码可能会对您有所帮助,

      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
      

      【讨论】:

      • 感谢您的建议!但是,这不会涵盖数组引用语法(“a.b[0].c”)的情况,但如果有人想从头开始实现它,这可能是一个很好的起点。
      【解决方案5】:

      您可以使用 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 结构设计您的模型类。

      【讨论】:

      • 谢谢,但由于没有预定义的结构,我无法创建与之匹配的类。我能做的唯一假设是该对象将是有效的 JSON。
      • 因为正如我的评论所解释的,这并不能回答问题:我无法创建 POJO 类,因为 JSONObject 每次都会代表不同的 JSON 结构。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-23
      • 1970-01-01
      • 2016-02-05
      • 1970-01-01
      • 1970-01-01
      • 2017-10-02
      • 2020-03-01
      相关资源
      最近更新 更多