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

fr.adbonnin.cz2128.json.JsonUtils Maven / Gradle / Ivy

The newest version!
package fr.adbonnin.cz2128.json;

import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import fr.adbonnin.cz2128.io.StreamUtils;

import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Spliterators;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

public class JsonUtils {

    public static final JsonEncoding DEFAULT_ENCODING = JsonEncoding.UTF8;

    private static final JsonFactory DEFAULT_EMPTY_JSON_PARSER_FACTORY = new JsonFactory(new JsonMapper());

    public static JsonParser newEmptyParser() throws IOException {
        return DEFAULT_EMPTY_JSON_PARSER_FACTORY.createParser(StreamUtils.nullInputStream());
    }

    public static LinkedHashMap mapFieldsToLinkedHashMap(JsonNode node) {
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(node.fields(), 0), false)
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
    }

    public static JsonNode readNode(JsonProvider provider) {
        return provider.withParser(JSON_NODE_READER);
    }

    public static void writeNode(JsonNode node, JsonProvider provider) {
        provider.withGenerator((parser, generator) -> {
            try {
                generator.writeTree(node);
                return null;
            }
            catch (IOException e) {
                throw new JsonException(e);
            }
        });
    }

    public static boolean partialUpdate(JsonNode oldNode, JsonNode newNode, JsonGenerator generator) throws IOException {

        if (oldNode == null && newNode == null) {
            return false;
        }
        else if (oldNode == null) {
            generator.writeTree(newNode);
            return true;
        }
        else if (newNode == null) {
            generator.writeTree(oldNode);
            return false;
        }

        if (oldNode.isObject() && newNode.isObject()) {
            return partialUpdateObject((ObjectNode) oldNode, (ObjectNode) newNode, generator);
        }
        else if (oldNode.isArray() && newNode.isArray()) {
            return partialUpdateArray((ArrayNode) oldNode, (ArrayNode) newNode, generator);
        }
        else {
            generator.writeTree(newNode);
            return !newNode.equals(oldNode);
        }
    }

    public static boolean partialUpdateObject(ObjectNode oldNode, ObjectNode newNode, JsonGenerator generator) throws IOException {

        if (oldNode == null && newNode == null) {
            return false;
        }
        else if (oldNode == null) {
            generator.writeTree(newNode);
            return true;
        }
        else if (newNode == null || newNode.isEmpty()) {
            generator.writeTree(oldNode);
            return false;
        }

        final Map newNodeCopy = mapFieldsToLinkedHashMap(newNode);
        generator.writeStartObject();

        // Update old fields
        final Iterator> oldFields = oldNode.fields();
        while (oldFields.hasNext()) {
            final Map.Entry oldField = oldFields.next();
            final String name = oldField.getKey();

            JsonNode newElt = newNodeCopy.remove(name);
            if (newElt == null) {
                newElt = oldField.getValue();
            }

            generator.writeFieldName(name);
            generator.writeTree(newElt);
        }

        // Create new fields
        for (Map.Entry newField : newNodeCopy.entrySet()) {
            generator.writeFieldName(newField.getKey());
            generator.writeTree(newField.getValue());
        }

        generator.writeEndObject();
        return true;
    }

    public static boolean partialUpdateArray(ArrayNode oldNode, ArrayNode newNode, JsonGenerator generator) throws IOException {

        if (oldNode == null && newNode == null) {
            return false;
        }
        else if (oldNode == null) {
            generator.writeTree(newNode);
            return true;
        }
        else if (newNode == null || newNode.isEmpty()) {
            generator.writeTree(oldNode);
            return false;
        }
        else if (oldNode.size() <= newNode.size()) {
            generator.writeTree(newNode);
            return true;
        }

        generator.writeStartArray();

        final Iterator newElements = newNode.iterator();
        boolean hasNewElements = true;

        for (JsonNode oldElement : oldNode) {
            hasNewElements &= newElements.hasNext();
            generator.writeTree(hasNewElements ? newElements.next() : oldElement);
        }

        generator.writeEndArray();
        return true;
    }

    private static final Function JSON_NODE_READER = parser -> {
        try {
            return parser.readValueAsTree();
        }
        catch (IOException e) {
            throw new JsonException(e);
        }
    };

    private JsonUtils() { /* Cannot be instantiated */ }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy