java - 使用json模板文件和json数据文件构建新的json字符串

原文 标签 java json gson

我有一个JSON模板文件如下

{
  "value": "abc",
  "Treatments": [{
    "value": "def",
    "Stages": [{
      "value": "ghi"
    }]
  }]
}


和一个JSON数据

{ "abc": {
    "labelabc": "Assembly name abc",
    "typeabc": "STRING_TYPE abc",
    "formatabc": "N abc"
  },
  "def": {
    "labeldef": "Assembly name def",
    "typedef": "STRING_TYPE def",
    "formatdef": "N def"
  },
  "ghi": {
    "labelghi": "Assembly name ghi",
    "typeghi": "STRING_TYPE ghi",
    "formatghi": "N ghi"
  }
}


我正在寻找一种将模板解析为的解决方案

{
  "labelabc": "Assembly name abc",
  "typeabc": "STRING_TYPE abc",
  "formatabc": "N abc",
  "Treatments": [
    {
      "labeldef": "Assembly name def",
      "typedef": "STRING_TYPE def",
      "formatdef": "N def",
      "Stages": [
        {
          "labelghi": "Assembly name ghi",
          "typeghi": "STRING_TYPE ghi",
          "formatghi": "N ghi"
        }
      ]
    }
  ]
}


意思是:


将“值”条目替换为json数据文件中的jsonobject值


我已经使用下面的代码通过2个级别的模板来实现结果。但是失败了以上三个级别的模板

public static JsonElement generateTemplate(JsonElement templateJson, JsonElement dataTemplate) {
if (templateJson.isJsonArray()) {
            for (JsonElement jsonElement1 : templateJson.getAsJsonArray()) {
                generateTemplate(jsonElement1, dataTemplate);
            }
        } else if (templateJson.isJsonObject()) {
            for (Iterator<Map.Entry<String, JsonElement>> iterator = templateJson.getAsJsonObject().entrySet()
                    .iterator(); iterator.hasNext();) {
                Map.Entry<String, JsonElement> entry = iterator.next();
                if (entry.getKey().equals("value")) {
                    templateJson = dataTemplate.getAsJsonObject().get(entry.getValue().getAsString()).getAsJsonObject();
                } else {
                    if (entry.getValue().isJsonObject()) {
                        generateTemplate(entry.getValue(), dataTemplate);
                    } else
                        templateJson.getAsJsonObject().add(entry.getKey(), p.parse(
                            dataTemplate.getAsJsonObject().get(entry.getValue().getAsString()).getAsJsonObject()
                                ));
                }

                generateTemplate(entry.getValue(), dataTemplate);
            }
        }

return templateJson;
}


非常感谢您的建议

最佳答案

您可以使用递归。这是主要思想,您可以稍后在modifyObject方法中根据需要调整实际替换,对于"value": "abc",该替换将期望对象保留在数据中。

"abc": {
    "labelabc": "Assembly name abc",
    "typeabc": "STRING_TYPE abc",
    "formatabc": "N abc"
}


private static void modifyObject(JsonObject obj, JsonObject replacement) {
    obj.remove("value");
    for (String key : replacement.keySet()) {
        obj.addProperty(key, replacement.get(key).getAsString());
    }
}

public static JsonElement traverse(JsonElement element, JsonObject allReplacements) {
    if (element.isJsonObject()) {
        JsonObject asJsonObject = element.getAsJsonObject();
        ///keys can change after we modify object,
        //but we want to iterate only over original keys
        Set<String> originalKeys = new HashSet<>(asJsonObject.keySet());
        for (String key : originalKeys) {
            if (key.equals("value")) {
                String value = asJsonObject.get(key).getAsString();
                modifyObject(asJsonObject, allReplacements.getAsJsonObject(value));
            } else {
                traverse(asJsonObject.get(key), allReplacements);
            }
        }
    } else if (element.isJsonArray()) {
        for (JsonElement innerElement : element.getAsJsonArray()) {
            traverse(innerElement, allReplacements);
        }
    }
    return element;
}


用法:

public static void main(String[] args) throws Exception {
    String jsonTemplate =
            "{\n" +
            "  \"value\": \"abc\",\n" +
            "  \"foo\": \"bar\",\n" +
            "  \"Treatments\": [ {\n" +
            "    \"value\": \"def\",\n" +
            "    \"Stages\": [ [ {\n" +
            "      \"value\": \"ghi\"\n" +
            "    } ] ]\n" +
            "  } ]\n" +
            "}";
    String jsonData = "{ \"abc\": {\n" +
            "    \"label\": \"Assembly name abc\",\n" +
            "    \"type\": \"STRING_TYPE abc\",\n" +
            "    \"format\": \"N\"\n" +
            "  },\n" +
            "  \"def\": {\n" +
            "    \"label\": \"Assembly name def\",\n" +
            "    \"type\": \"STRING_TYPE\",\n" +
            "    \"format\": \"N\"\n" +
            "  },\n" +
            "  \"ghi\": {\n" +
            "    \"label\": \"Assembly name ghi\",\n" +
            "    \"type\": \"STRING_TYPE\",\n" +
            "    \"format\": \"N\"\n" +
            "  }\n" +
            "}";


    JsonParser jsonParser = new JsonParser();
    JsonElement template = jsonParser.parse(jsonTemplate);
    JsonObject data = (JsonObject) jsonParser.parse(jsonData);

    JsonElement obj = template.deepCopy();//in case we don't want to modify original template

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    System.out.println(gson.toJson(traverse(obj, data)));

}


输出:

{
  "foo": "bar",
  "Treatments": [
    {
      "Stages": [
        [
          {
            "label": "Assembly name ghi",
            "type": "STRING_TYPE",
            "format": "N"
          }
        ]
      ],
      "label": "Assembly name def",
      "type": "STRING_TYPE",
      "format": "N"
    }
  ],
  "label": "Assembly name abc",
  "type": "STRING_TYPE abc",
  "format": "N"
}

关于java - 使用json模板文件和json数据文件构建新的json字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56175923/

相关文章:

ruby-on-rails - Rails Serializer 不过滤数据

javascript - 全局声明forEach并在函数中使用它

java - java扫描仪获取数据并检测到输入每个数字和字符

java - OSGi:如何知道捆绑包是否已更新

javascript - 将参数作为数组传递的 Angular (例如?category [] = 1&category [] = 2&category [] = 3)

java - 使用 Gson(或 java 的替代方法)解析 JSON

java - 从 Spring Controller 返回 json View 的步骤

java - 将数据放入分布式 map 时,Hazelcast 很慢

java - Jersey 未验证实体

java - 在 SharedPreference 中保存通用类型的 List