All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.api.jsonata4java.expressions.utils.JsonMergeUtils Maven / Gradle / Ivy

There is a newer version: 2.5.1
Show newest version
/**
 * (c) Copyright 2018, 2019 IBM Corporation
 * 1 New Orchard Road, 
 * Armonk, New York, 10504-1722
 * United States
 * +1 914 499 1900
 * support: Nathaniel Mills [email protected]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.api.jsonata4java.expressions.utils;

import java.util.Iterator;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * A utility for merging arbitrary JSON trees. Used during default state
 * generation to combine explicit and implicit default values where necessary.
 */
public class JsonMergeUtils {

	/**
	 * Returns x "merged into" y
	 * 
	 * If x is null (java null, not JSON null!), return y
	 * 
	 * If y is (java null, not JSON null!), return x
	 * 
	 * If both x and y are primitive (including JSON null!), return x (i.e. values
	 * in x take precedence over those in y)
	 * 
	 * If x and y are of different types, return x
	 * 
	 * If x and y are both objects, merge each field of x and y
	 * 
	 * If an array field is set in both x and y, merge will be run on each element
	 * in turn. the length of the returned array will be max( length(x), length(y) )
	 * 
	 * 
	 * See src/test/resources/JsonMergeUtilsTest.json for examples.
	 * 
	 * @param x Json object
	 * @param y Json object
	 * @return merged Json object
	 */
	public static JsonNode merge(JsonNode x, JsonNode y) {
		if (x == null) {
			return y;
		} else if (y == null) {
			return x;
		} else if (x.isObject() && y.isObject()) {
			return merge((ObjectNode) x, (ObjectNode) y);
		} else if (x.isArray() && y.isArray()) {
			return merge((ArrayNode) x, (ArrayNode) y);
		} else {
			return x;
		}
	}

	private static ObjectNode merge(ObjectNode x, ObjectNode y) {

		final Iterator> yit = y.fields();
		while (yit.hasNext()) {
			final Map.Entry ye = yit.next();
			final String f = ye.getKey();
			final JsonNode yv = ye.getValue();
			final JsonNode xv = x.get(f);
			x.set(f, merge(xv, yv));
		}

		// and return the merged view
		return x;

	}

	private static ArrayNode merge(ArrayNode x, ArrayNode y) {
		final ArrayNode output = JsonNodeFactory.instance.arrayNode();

		for (int i = 0; i < x.size() || i < y.size(); i++) {
			JsonNode xv = i < x.size() ? x.get(i) : null;
			JsonNode yv = i < y.size() ? y.get(i) : null;
			output.add(merge(xv, yv));

		}
		return output;

	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy