【问题标题】:Iterate all json object and replace values迭代所有 json 对象并替换值
【发布时间】:2023-03-20 09:33:01
【问题描述】:

我有以下 JSON:

{  
   "data":{  
      "attributes":{  
         "external-event-url":"http://example.com",
         "is-sponsors-enabled":"true",
         "is-ticketing-enabled":"true",
         "timezone":"UTC",
         "name":"${name_variable}",
         "ends-at":"2020-01-02T23:59:59.123456+00:00",
         "starts-at":"2020-01-01T23:59:59.123456+00:00"
      },
      "type":"event"
   }
}

我必须遍历 json 对象并替换以 ${ 开头的变量的值,例如${name_variable} 并且新的 json 格式应该相同(替换提到的变量值${}

我如何迭代如此复杂的 Json 对象并替换变量中的值

我尝试了下面的代码,但没有按预期工作:

public Map<String, String> mapfillData(String jsonstr) {
    Map<String, String> map = new HashMap<String, String>();
    try {
        JSONObject jsonObject = new JSONObject(jsonstr);
        String[] keys = JSONObject.getNames(jsonObject);

        for (String key : keys) {
            try {
                if (jsonObject.get(key).toString().startsWith("${")) {
                    map.put(key, System.getProperty(jsonObject.get(key).toString()
                            .replace("${", "").replace("}", "")));
                } else {
                    if(isJSONValid(jsonObject.get(key).toString())){
                        mapfillData(jsonObject.get(key).toString());
                    }else{
                        map.put(key, jsonObject.get(key).toString());
                    }
                }

            } catch (Exception e) {

            }
        }
    } catch (JSONException e) {
        System.err.printf(jsonstr + " is not valid Json", e);
    }
    return map;
}

检查它是否是一个有效的 JSON 对象

public boolean isJSONValid(String test) {
    try {
        new JSONObject(test);
    } catch (JSONException ex) {
        // edited, to include @Arthur's comment
        // e.g. in case JSONArray is valid as well...
        try {
            new JSONArray(test);
        } catch (JSONException ex1) {
            return false;
        }
    }
    return true;
}

【问题讨论】:

  • “我如何迭代如此复杂的 Json 对象并替换变量中的值”,递归。如果它是一个 JSONObject 然后下降到它并迭代它的孩子如果孩子是一个 JSONObject 然后递归。
  • @xtratic,这就是我试图实现相同的逻辑。但不知道我在哪里犯了错误。
  • 问问自己,只对整个 JSON 文本进行替换是否会更好。但如果您决定不这样做,那么最好先将 JSON 转换为对象,然后调用接受 JSONObject 而不是字符串的递归方法,并避免从字符串到对象的所有转换。
  • 请发布您的所有代码。 isJSONValid() 是什么样的?
  • @StvnBrkdll,已更新。此方法用于检查特定键的值是否为 JSON 对象,如果是则递归

标签: java json iterator


【解决方案1】:

您的问题是,当您尝试递归处理 JSON 时,在每个递归级别,您正在处理一个 不同 JSON 文档并将数据写入一个 不同 Map.

您的函数接受一个字符串,然后将其解析为JSONObject。您创建一个Map 来保存一些数据。第一次通过mapfillData,您只会找到一个密钥data。然后,假设您的if 逻辑工作正常(我没有尝试运行它),您将把data 的内容渲染到另一个字符串中并递归调用mapfillData

现在您正在第二次调用mapfillData,并创建另一个Map。这次通过您找到attributes 并第三次致电mapfillData。在第三次调用中,您会找到一些变量并在将值写入Map 时替换它们。在函数结束时,您返回了Map,但调用者(mapfillData 的第二次调用)没有对返回的Map 执行任何操作,并且您的所有数据都丢失了。

我愿意:

  • 解析一次 JSON,然后通过 JSONObject 结构递归。换句话说,递归函数应该采用 JSONObject。
  • 只需就地替换 JSON 元素即可。
  • 或者,如果您想展平元素并将它们收集到 Map 中,则预先实例化 Map 并将其传递给递归函数。

【讨论】:

    【解决方案2】:

    为了更轻松地转换,您可以使用 Jackson 库来做一些困难的事情:

    ObjectMapper mapper = new ObjectMapper();
    String jsonString = "{  
       "data":{  
          "attributes":{  
             "external-event-url":"http://example.com",
             "is-sponsors-enabled":"true",
             "is-ticketing-enabled":"true",
             "timezone":"UTC",
             "name":"${name_variable}",
             "ends-at":"2020-01-02T23:59:59.123456+00:00",
             "starts-at":"2020-01-01T23:59:59.123456+00:00"
          },
          "type":"event"
       }
    }";
    
    // considering JSONObject matches the Json object structure
    JSONObject jsonObject = mapper.readValue(jsonString , JSONObject.class); 
    

    然后一点点reflection 来动态处理任何 JSON 对象字段:

    // with parsed JSON to Object in hands
    Class<?> clazz = jsonObject.getClass();
    
    for(Field field : clazz.getDeclaredFields()) {
        if(!field.getType().getName().equals("String"))
            break;
    
        field.setAccessible(true);
        String fieldValue = field.getValue().toString();
    
        if(fieldValue.startsWith("${"))
            field.set(jsonObject, fieldValue.replace("${", "").replace("}", ""));
        else
            // desired treatment
    }
    

    【讨论】:

      猜你喜欢
      • 2016-12-30
      • 2019-04-13
      • 2015-04-22
      • 1970-01-01
      • 2011-10-13
      • 1970-01-01
      • 2015-12-22
      • 1970-01-01
      • 2017-10-25
      相关资源
      最近更新 更多