gson 在Java中合并多个JSON对象(可能包含数组)[duplicate]

ar5n3qh5  于 2022-11-23  发布在  Java
关注(0)|答案(2)|浏览(212)

此问题在此处已有答案

Merge/Extend JSON Objects using Gson in Java(4个答案)
去年关闭了。
给定此JSON:

{
  "contact_data": [
    "address/all",
    "telephone/us"
  ],
  "financial_data": [
    "bank_account_number/all",
    "bank_account_number/uk",
    "credit_card_numbers"
  ]
}

以及这个JSON:

{
  "financial_data": [
    "credit_card_numbers",
    "bank_account_number/ca",
    "bank_account_number/all"
  ],
  "government_id": [
    "driving_license/americas"
  ],
  "sensitive_data": [
    "racial_ethnic_origin"
  ]
}

我想将这些合并为如下所示:

{
  "contact_data": [
    "address/all",
    "telephone/us"
  ],
  "financial_data": [
    "credit_card_numbers",
    "bank_account_number/ca",
    "bank_account_number/uk",
    "bank_account_number/all"
  ],
  "government_id": [
    "driving_license/americas"
  ],
  "sensitive_data": [
    "racial_ethnic_origin"
  ]
}

我有以下几种方法,几乎都能奏效:

import org.json.JSONObject;
...
final List<String> jsonStrings = ...; // A list of the above sample JSONs
final List<JSONObject> jsonObjects = jsonStrings
      .stream()
      .map(JSONObject::new)
      // JSONObject.getNames() (called later on) will return null if JSONObject is empty, so filter out empty objects.
      .filter(jsonObject -> !jsonObject.isEmpty()) 
      .collect(Collectors.toList());
if (jsonObjects..size() > 1) {
    // Merge multiple JSONObjects: https://stackoverflow.com/a/2403453/12177456
    final JSONObject firstJsonObject = jsonObjects.get(0);
    final JSONObject merged = new JSONObject(firstJsonObject, JSONObject.getNames(firstJsonObject));
    final List<JSONObject> remainingJsonObjects = jsonObjects.subList(1, jsonObjects.size());
    for (final JSONObject nextJsonObject : remainingJsonObjects) {
        for (final String nextJsonObjectFieldName : JSONObject.getNames(nextJsonObject)) {
            merged.put(nextJsonObjectFieldName, nextJsonObject.get(nextJsonObjectFieldName));
        }
    }
    return merged;
}

但是,我希望在financial_data中看到4个条目:

...
"financial_data": [
    "bank_account_number/all",
    "bank_account_number/uk",
    "bank_account_number/ca",
    "credit_card_numbers"
  ]
...

相反,我只看到3,bank_account_number/uk不在合并结果中:

...
"financial_data": [
    "bank_account_number/all",
    "bank_account_number/ca",
    "credit_card_numbers"
  ]
...

我没有坚持使用org.json,如果使用gson,Jackson,普通的JavaMap更简单,我可以接受。

xzv2uavs

xzv2uavs1#

实际上,这行不通。问题就在这里:

merged.put(nextJsonObjectFieldName, nextJsonObject.get(nextJsonObjectFieldName))

这将用后面的一个替换键为nextJsonObjectFieldName的条目,这就是为什么要从第二个对象中获取financial_data

{
    "financial_data": [
        "credit_card_numbers",
        "bank_account_number/ca",
        "bank_account_number/all"
    ]
}

您看到的其他键是正确的,因为其他键在两个JSON中具有完全相同的值。如果您在第二个json中也更改其他键的值,您将看到合并后的JSON将具有与第二个json中的键相同的值。也就是说,它不起作用。
你可以做的是,你可以检查这个键在map中是否已经有了值。如果这个键没有现有的JSON对象,就把它放到merged中。否则,我们还有更多的工作要做:

JSONObject jsonObject = merged.get(nextJsonObjectFieldName);
if (jsonObject != null) {
    final JSONObject finalObj = mergeJsonObjectCheckingFieldValues(jsonObject, nextJsonObject.get(nextJsonObjectFieldName));
    merged.put(nextJsonObjectFieldName, finalObj);
} else {
    merged.put(nextJsonObjectFieldName, nextJsonObject.get(nextJsonObjectFieldName));
}

mergeJsonObjectCheckingFieldValues方法检查给定的两个JSONObject之间的每个元素,并比较它们是否相同。根据您的示例,为了简单地回答这个问题,我假设每个JSONObject都是一个String列表。为此,我们将需要objectMapper。因此,请确保您的项目中有com.fasterxml.jackson.databind.ObjectMapper。因此,检查将是:

ObjectMapper mapper = new ObjectMapper();

public JSONObject mergeJsonObjectCheckingFieldValues(JSONObject jsonObject, JSONObject nextJsonObject)) {
    List<String> existingList = Arrays.asList(mapper
                    .readValue(jsonObject.toString(), String[].class));

    List<String> newList = Arrays.asList(mapper
                    .readValue(nextJsonObject.toString(), String[].class));
    
    List<String> toBeAdded = newList
                                .stream()
                                .filter(x -> !existingList.contains(x))
                                .collect(Collectors.toList());

    if(toBeAdded.size() > 0) {
        existingList.addAll(toBeAdded);
    }
    return new JSONObject(JSONArray.toJSONString(existingList));
}

这是你的问题的可能的解决方案。我还没有测试过它,但是代码应该差不多是这样的。

moiiocjp

moiiocjp2#

在这里我使用gson给出了公认的答案:
https://stackoverflow.com/a/34092374/12177456

  • 处理递归合并JsonObject
  • 当键同时存在于两个Map中时处理冲突
  • 对数组等非基元值进行特殊处理

相关问题