【问题标题】:Check whether a key exists or not in a nested JSON检查嵌套 JSON 中是否存在键
【发布时间】:2015-06-25 07:14:16
【问题描述】:

我陷入了需要检查嵌套 JSON 对象中是否存在键的情况。通过嵌套的 JSON 对象,我在父 JSON 对象中有一个 JSON 对象作为其键之一的值。所以我需要检查这个键是否存在于整个 JSON 对象中。我将以下数据作为String 对象获取。我知道我可以解析这个 String 对象来获取 JSON 对象。

{
"claim_loss_type_cd": "TEL",
"claim_type": "002",
"claim_reason": "001",
"policy_number": "1234kk3366ff664",
"info": {
    "ApplicationContext": {
        "country": "US"
    }
  }
}

我已使用containsKey() 方法检查主 JSON 对象中的密钥是否存在并且它有效。但为了检查任何内部 JSON 对象,如“信息”,我需要再次将 Object 解析为 JSON 对象,然后再次检查密钥。

        String jsonString = "My JSON String here";
        JSONObject finalResponse = new JSONObject(jsonString);
        finalResponse.containsKey("country"); // will return false
        JSONObject intermediateResponse = (JSONObject)finalResponse.get("info");
        intermediateResponse.containsKey("country"); // will return true

那么有没有更好的方法,任何 API 或方法都可以检查任何内部 JSON 对象,而无需解析内部 JSON 对象。我正在为 Websphere Application Server 使用 com.ibm.json.java.JSONObject.JSONObject() 本机 IBM 库,并且我没有使用其他 JSON 解析器。

考虑到上面的 JSON,像“claim_type”是父 JSON 对象中的一个键,但“info”本身是一个 JSON 对象。 所以我需要做的是检查一个键是否存在于完整的 JSON 中,无论是在父级还是它的任何子 JSON 对象中,例如这里的键“国家”。

编辑:

感谢@chsdk,我找到了解决方案。但是,如果其他人使用其他 API 找到任何解决方案,请回复,因为下面的解决方案考虑了递归并且可能具有很大的空间/时间复杂性。

public static boolean checkKey(JSONObject object, String searchedKey) {
    boolean exists = object.containsKey(searchedKey);
    if(!exists) {      
         Set<String> keys = object.keySet();
         for(String key : keys){
             if ( object.get(key) instanceof JSONObject ) {
                    exists = checkKey((JSONObject)object.get(key), searchedKey);
            }
         }
    }
    return exists;
}

【问题讨论】:

  • 你是否使用过任何 JSON 解析器,例如 jakson 等?
  • 各位,JSON(这个词)不是代码,不要把它格式化成代码块..
  • @TimCastelijns 有人建议我将 JSON 用作代码,所以我接受了该建议进行编辑
  • 如果您将 JSON 作为原始字符串,是否可以对照正则表达式 \"country\"\s*: 对其进行检查?
  • @MuhammadSuleman 不,我没有使用任何其他解析器

标签: java json


【解决方案1】:

您可以使用 JSONObject 来解析您的 json 并使用其 has(String key) 方法检查此 Json 中是否存在密钥与否:

 String str="{\"claim_loss_type_cd\": \"TEL\",\"claim_type\":\"002\",\"claim_reason\": \"001\",\"policy_number\":\"1234kk3366ff664\",\"info\": {\"ApplicationContext\":{\"country\": \"US\"}}}";
 Object obj=JSONValue.parse(str);
 JSONObject json = (JSONObject) obj;
 //Then use has method to check if this key exists or not
 System.out.println(json.has("claim_type")); //Returns true

编辑:

或者更好的是,您可以简单地检查 JSON 字符串是否包含此键值,例如使用 indexOf() 方法:

String str="{\"claim_loss_type_cd\": \"TEL\",\"claim_type\":\"002\",\"claim_reason\": \"001\",\"policy_number\":\"1234kk3366ff664\",\"info\": {\"ApplicationContext\":{\"country\": \"US\"}}}";
System.out.println(str.indexOf("claim_type")>-1); //Returns true

编辑 2:

看看这个方法,它遍历嵌套对象来检查键是否存在。

public boolean keyExists(JSONObject  object, String searchedKey) {
    boolean exists = object.has(searchedKey);
    if(!exists) {      
        Iterator<?> keys = object.keys();
        while( keys.hasNext() ) {
            String key = (String)keys.next();
            if ( object.get(key) instanceof JSONObject ) {
                    exists = keyExists(object.get(key), searchedKey);
            }
        }
    }
    return exists;
}

Object obj=JSONValue.parse(str);
JSONObject json = (JSONObject) obj;
System.out.println(keyExists(json, "country")); //Returns true

【讨论】:

  • 我已经编辑了我的问题以获得正确的解释。我不想解析内部 JSON 对象。这个has() 方法是不是可以检查整个json String 并且可以检查一个键是否存在
  • 不,它不检查内部 JSONObjects,但您可以直接从头开始检查字符串中键的存在。
  • 谢谢,但我实际上想检查任何 JSON 方法而不是使用字符串进行操作
  • 是的,看起来很有希望并且可能会解决需求,但是性能问题呢,将其称为方法 keyExists() 递归
  • 递归调用是没有问题的,可以看到key退出后不会从头进入循环,只有嵌套的JSONObjects才会递归调用。
【解决方案2】:

具有正确类型转换的现成方法:

/**
 * JSONObject contains the given key. Search is also done in nested 
 * objects recursively.
 *
 * @param json JSONObject to serach in.
 * @param key Key name to search for.
 * @return Key is found.
 */
public static boolean hasKey(
  JSONObject json,
  String key) {

  boolean exists = json.has(key);
  Iterator<?> keys;
  String nextKey;

  if (!exists) {

    keys = json.keys();

    while (keys.hasNext()) {
      nextKey = (String) keys.next();

      try {
        if (json.get(nextKey) instanceof JSONObject) {
          exists =
            hasKey(
              json.getJSONObject(nextKey),
              key);
        }
      } catch (JSONException e) {
        e.printStackTrace();
      }
    }
  }

  return exists;
}

【讨论】:

    【解决方案3】:

    这两种建议递归迭代 JsonObject 的解决方案都有一个小错误:当最终找到搜索到的键时,它们不会中断迭代。所以你必须打破while循环,否则循环将继续,如果有下一个键,它会检查这个键等等。 仅搜索“country”键的代码示例有效,因为“country”恰好是其 JsonObject 中的最后一个键。

    例子:

     /* ... */
        while (keys.hasNext()) {
              nextKey = (String) keys.next();
    
              try {
                if (json.get(nextKey) instanceof JSONObject) {
                  exists = hasKey(json.getJSONObject(nextKey), key);
    
                  if(exists){
                      break;
                  }
    
                }
              } catch (JSONException e) {
                e.printStackTrace();
              }
            }
        /* ... */
    

    【讨论】:

      【解决方案4】:

      我遇到了类似的问题需要克服,将 JSON 转换为 Map 并收集键值对并迭代它们以获得我需要的值(它一次又一次地调用相同的方法,但感觉比递归编程更好。希望它有所帮助)。

      public static void jsonToMap(String t) throws JSONException {
      
          Map<String,String> map = new HashMap<>();
          getJsonObjectMap(t).entrySet()
              .stream()
              .filter(s->s.getKey().equals("info"))
              .forEach(u -> {
                  try {
                      getJsonObjectMap(u.getValue()).forEach(map::put);
                  } catch (JSONException e) {
                      e.printStackTrace();
                  }
              });
              
          map.entrySet().forEach(System.out::println);
      
      }
      
      private static Map<String,String> getJsonObjectMap(String t) throws JSONException {
      
          HashMap<String,String>  map = new HashMap<>();
          JSONObject jObject = new JSONObject(t);
          Iterator<?> keys = jObject.keys();
          while( keys.hasNext() ){
              String key = (String)keys.next();
              String value = jObject.getString(key);
              map.put(key, value);
          }
          return map;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-09
        • 1970-01-01
        • 2021-02-28
        相关资源
        最近更新 更多