Jackson을 사용한 두 개의 JSON 문서 병합
JSON 문서 두 개를 Jackson JSON 라이브러리와 병합할 수 있습니까?기본적으로 잭슨 맵을 간단한 자바 맵과 함께 사용하고 있습니다.
구글과 잭슨의 문서를 검색해 보았지만 아무것도 찾을 수 없었습니다.
Stax Mans의 답변에서 영감을 얻어 이 병합 방법을 구현했습니다.
public static JsonNode merge(JsonNode mainNode, JsonNode updateNode) {
Iterator<String> fieldNames = updateNode.fieldNames();
while (fieldNames.hasNext()) {
String fieldName = fieldNames.next();
JsonNode jsonNode = mainNode.get(fieldName);
// if field exists and is an embedded object
if (jsonNode != null && jsonNode.isObject()) {
merge(jsonNode, updateNode.get(fieldName));
}
else {
if (mainNode instanceof ObjectNode) {
// Overwrite field
JsonNode value = updateNode.get(fieldName);
((ObjectNode) mainNode).put(fieldName, value);
}
}
}
return mainNode;
}
이게 도움이 됐으면 좋겠네요.
한 가지 방법은ObjectReader
다음과 같이 합니다.
MyBean defaults = objectMapper.readValue(defaultJson, MyBean.class);
ObjectReader updater = objectMapper.readerForUpdating(defaults);
MyBean merged = updater.readValue(overridesJson);
두 소스의 데이터를 결합합니다.이렇게 하면 얕은 복사본만 생성됩니다. 즉, 포함된 개체에 대해 재귀 병합을 수행하지 않습니다.
그렇지 않으면 JSON을 트리로 읽어야 할 수도 있습니다(JsonNode
콘텐츠를 루프오버하고 수동으로 Marge합니다.병합 규칙이 사소한 것이 아니고, 모든 사람이 병합이 어떻게 작동해야 하는지에 대한 자신만의 생각을 가지고 있기 때문에, 어쨌든 이것은 종종 이치에 맞는다.
편집: (2017년 4월 3일)
@Fernando Correia의 코멘트에 따르면, Jackson 2.9(2017년 4월 또는 5월 출시 예정)에 최종적으로 깊은 통합을 가능하게 하는 새로운 기능이 추가되었습니다.
아른의 대답에 영감을 받아.편집하여 노드에 노드 배열이 있을 수 있는 경우를 추가합니다.
public static JsonNode merge(JsonNode mainNode, JsonNode updateNode) {
Iterator<String> fieldNames = updateNode.fieldNames();
while (fieldNames.hasNext()) {
String updatedFieldName = fieldNames.next();
JsonNode valueToBeUpdated = mainNode.get(updatedFieldName);
JsonNode updatedValue = updateNode.get(updatedFieldName);
// If the node is an @ArrayNode
if (valueToBeUpdated != null && valueToBeUpdated.isArray() &&
updatedValue.isArray()) {
// running a loop for all elements of the updated ArrayNode
for (int i = 0; i < updatedValue.size(); i++) {
JsonNode updatedChildNode = updatedValue.get(i);
// Create a new Node in the node that should be updated, if there was no corresponding node in it
// Use-case - where the updateNode will have a new element in its Array
if (valueToBeUpdated.size() <= i) {
((ArrayNode) valueToBeUpdated).add(updatedChildNode);
}
// getting reference for the node to be updated
JsonNode childNodeToBeUpdated = valueToBeUpdated.get(i);
merge(childNodeToBeUpdated, updatedChildNode);
}
// if the Node is an @ObjectNode
} else if (valueToBeUpdated != null && valueToBeUpdated.isObject()) {
merge(valueToBeUpdated, updatedValue);
} else {
if (mainNode instanceof ObjectNode) {
((ObjectNode) mainNode).replace(updatedFieldName, updatedValue);
}
}
}
return mainNode;
}
Scala에서의 실장은 다음과 같습니다.소스 노드와 타깃노드는 브랜치가 소스와 타깃 양쪽에 존재하는 경우를 제외하고 대부분 가환적입니다.
def mergeYamlObjects(source: ObjectNode, target: ObjectNode, overwrite: Boolean = true): ObjectNode = {
if (target == null)
source
else if (source == null)
target
else {
val result = source.deepCopy
val fieldlist = source.fieldNames.asScala.toList ++ target.fieldNames.asScala.toList
for (item <- fieldlist) {
if (!(source has item)) {
result put(item, target get item)
} else {
if ((source get item).isValueNode) {
if (target has item)
if (overwrite)
result.put(item, target get item)
} else {
result.put(item, mergeYamlObjects(source.get(item).asInstanceOf[ObjectNode],
target.get(item).asInstanceOf[ObjectNode], overwrite = overwrite))
}
}
}
result
}
}
단순히 두 개 이상의 JsonNode 개체를 하나의 JsonNode에 추가하는 경우 다음과 같은 방법이 있습니다.
ArrayNode arrayNode = objectMapper.createArrayNode();
arrayNode.add(firstJsonNode);
arrayNode.add(secondJsonNode);
arrayNode.add(thirdJsonNode);
JsonNode root = JsonNodeFactory.instance.objectNode();
((ObjectNode) root).put("", arrayNode);
System.out.println("merged array node #: " + root);
여기서 두 개의 JSON 트리를 하나로 병합하는 완전한 구현입니다.도움이 되었으면 합니다:)
/**
* Merge two JSON tree into one i.e mergedInTo.
*
* @param toBeMerged
* @param mergedInTo
*/
public static void merge(JsonNode toBeMerged, JsonNode mergedInTo) {
Iterator<Map.Entry<String, JsonNode>> incomingFieldsIterator = toBeMerged.fields();
Iterator<Map.Entry<String, JsonNode>> mergedIterator = mergedInTo.fields();
while (incomingFieldsIterator.hasNext()) {
Map.Entry<String, JsonNode> incomingEntry = incomingFieldsIterator.next();
JsonNode subNode = incomingEntry.getValue();
if (subNode.getNodeType().equals(JsonNodeType.OBJECT)) {
boolean isNewBlock = true;
mergedIterator = mergedInTo.fields();
while (mergedIterator.hasNext()) {
Map.Entry<String, JsonNode> entry = mergedIterator.next();
if (entry.getKey().equals(incomingEntry.getKey())) {
merge(incomingEntry.getValue(), entry.getValue());
isNewBlock = false;
}
}
if (isNewBlock) {
((ObjectNode) mergedInTo).replace(incomingEntry.getKey(), incomingEntry.getValue());
}
} else if (subNode.getNodeType().equals(JsonNodeType.ARRAY)) {
boolean newEntry = true;
mergedIterator = mergedInTo.fields();
while (mergedIterator.hasNext()) {
Map.Entry<String, JsonNode> entry = mergedIterator.next();
if (entry.getKey().equals(incomingEntry.getKey())) {
updateArray(incomingEntry.getValue(), entry);
newEntry = false;
}
}
if (newEntry) {
((ObjectNode) mergedInTo).replace(incomingEntry.getKey(), incomingEntry.getValue());
}
}
ValueNode valueNode = null;
JsonNode incomingValueNode = incomingEntry.getValue();
switch (subNode.getNodeType()) {
case STRING:
valueNode = new TextNode(incomingValueNode.textValue());
break;
case NUMBER:
valueNode = new IntNode(incomingValueNode.intValue());
break;
case BOOLEAN:
valueNode = BooleanNode.valueOf(incomingValueNode.booleanValue());
}
if (valueNode != null) {
updateObject(mergedInTo, valueNode, incomingEntry);
}
}
}
private static void updateArray(JsonNode valueToBePlaced, Map.Entry<String, JsonNode> toBeMerged) {
toBeMerged.setValue(valueToBePlaced);
}
private static void updateObject(JsonNode mergeInTo, ValueNode valueToBePlaced,
Map.Entry<String, JsonNode> toBeMerged) {
boolean newEntry = true;
Iterator<Map.Entry<String, JsonNode>> mergedIterator = mergeInTo.fields();
while (mergedIterator.hasNext()) {
Map.Entry<String, JsonNode> entry = mergedIterator.next();
if (entry.getKey().equals(toBeMerged.getKey())) {
newEntry = false;
entry.setValue(valueToBePlaced);
}
}
if (newEntry) {
((ObjectNode) mergeInTo).replace(toBeMerged.getKey(), toBeMerged.getValue());
}
}
2개의 JSON을 연결하는 것이 목표인 경우 가장 간단한 방법은 다음과 같습니다(2개의 Objec Node가 준비되어 있는 것을 고려).
ObjectMapper mapper = new ObjectMapper();
// Dummy objects to concatenate
Map<String, Object> map = new HashMap();
map.put("k", "v");
Map<String, Object> secondMap = new HashMap();
secondMap.put("secondK", "secondV");
//Transforming Objects into ObjectNode
ObjectNode firstObjectNode = mapper.convertValue(map, ObjectNode.class);
ObjectNode secondObjectNode = mapper.convertValue(secondMap, ObjectNode.class);
//Concatenating secondObjectNode into firstObjectNode
firstObjectNode.setAll(secondObjectNode);
//Output will be: {"k":"v","secondK":"secondV"}
System.out.println(firstObjectNode);
도움이 되었으면 좋겠다
언급URL : https://stackoverflow.com/questions/9895041/merging-two-json-documents-using-jackson
'programing' 카테고리의 다른 글
Angular 2에서 HTML 템플릿 인쇄(Angular 2에서 ng-print) (0) | 2023.03.11 |
---|---|
DataTables: 정의되지 않은 속성 '길이'를 읽을 수 없습니다. (0) | 2023.03.11 |
웹 스크랩 - Angular.js를 통해 JavaScript에 렌더링된 콘텐츠에 액세스하는 방법 (0) | 2023.03.11 |
타이프스크립트:네스트된 객체의 인터페이스를 정의하려면 어떻게 해야 합니까? (0) | 2023.03.11 |
Rails 앱에서 Wordpress 테마를 사용하려면? (0) | 2023.03.11 |