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

com.github.fge.jsonpatch.JsonPatch Maven / Gradle / Ivy

Go to download

JSON Patch (RFC 6902) and JSON Merge Patch (RFC 7386) implementation in Java

The newest version!
/*
 * Copyright (c) 2014, Francis Galiegue ([email protected])
 *
 * This software is dual-licensed under:
 *
 * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
 *   later version;
 * - the Apache Software License (ASL) version 2.0.
 *
 * The text of this file and of both licenses is available at the root of this
 * project or, if you have the jar distribution, in directory META-INF/, under
 * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
 *
 * Direct link to the sources:
 *
 * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
 * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
 */

package com.github.fge.jsonpatch;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializable;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.github.fge.jackson.JacksonUtils;
import com.github.fge.msgsimple.bundle.MessageBundle;
import com.github.fge.msgsimple.load.MessageBundles;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Implementation of JSON Patch
 *
 * 

JSON * Patch, as its name implies, is an IETF RFC describing a mechanism to * apply a patch to any JSON value. This implementation covers all operations * according to the specification; however, there are some subtle differences * with regards to some operations which are covered in these operations' * respective documentation.

* *

An example of a JSON Patch is as follows:

* *
 *     [
 *         {
 *             "op": "add",
 *             "path": "/-",
 *             "value": {
 *                 "productId": 19,
 *                 "name": "Duvel",
 *                 "type": "beer"
 *             }
 *         }
 *     ]
 * 
* *

This patch contains a single operation which adds an item at the end of * an array. A JSON Patch can contain more than one operation; in this case, all * operations are applied to the input JSON value in their order of appearance, * until all operations are applied or an error condition is encountered.

* *

The main point where this implementation differs from the specification * is initial JSON parsing. The draft says:

* *
 *     Operation objects MUST have exactly one "op" member
 * 
* *

and:

* *
 *     Additionally, operation objects MUST have exactly one "path" member.
 * 
* *

However, obeying these to the letter forces constraints on the JSON * parser. Here, these constraints are not enforced, which means:

* *
 *     [ { "op": "add", "op": "remove", "path": "/x" } ]
 * 
* *

is parsed (as a {@code remove} operation, since it appears last).

* *

IMPORTANT NOTE: the JSON Patch is supposed to be VALID when the * constructor for this class ({@link JsonPatch#fromJson(JsonNode)} is used.

*/ public final class JsonPatch implements JsonSerializable, Patch { private static final MessageBundle BUNDLE = MessageBundles.getBundle(JsonPatchMessages.class); /** * List of operations */ private final List operations; /** * Constructor * *

Normally, you should never have to use it.

* * @param operations the list of operations for this patch * @see JsonPatchOperation */ @JsonCreator public JsonPatch(final List operations) { this.operations = Collections.unmodifiableList(new ArrayList(operations)); } /** * Static factory method to build a JSON Patch out of a JSON representation * * @param node the JSON representation of the generated JSON Patch * @return a JSON Patch * @throws IOException input is not a valid JSON patch * @throws NullPointerException input is null */ public static JsonPatch fromJson(final JsonNode node) throws IOException { BUNDLE.checkNotNull(node, "jsonPatch.nullInput"); return JacksonUtils.getReader().forType(JsonPatch.class) .readValue(node); } /** * Apply this patch to a JSON value * * @param node the value to apply the patch to * @return the patched JSON value * @throws JsonPatchException failed to apply patch * @throws NullPointerException input is null */ @Override public JsonNode apply(final JsonNode node) throws JsonPatchException { BUNDLE.checkNotNull(node, "jsonPatch.nullInput"); JsonNode ret = node; for (final JsonPatchOperation operation: operations) ret = operation.apply(ret); return ret; } @Override public String toString() { return operations.toString(); } @Override public void serialize(final JsonGenerator jgen, final SerializerProvider provider) throws IOException { jgen.writeStartArray(); for (final JsonPatchOperation op: operations) op.serialize(jgen, provider); jgen.writeEndArray(); } @Override public void serializeWithType(final JsonGenerator jgen, final SerializerProvider provider, final TypeSerializer typeSer) throws IOException { serialize(jgen, provider); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy