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

com.github.fge.jsonpatch.operation.AddOperation 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.operation;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.fge.jackson.jsonpointer.JsonPointer;
import com.github.fge.jackson.jsonpointer.ReferenceToken;
import com.github.fge.jackson.jsonpointer.TokenResolver;
import com.github.fge.jsonpatch.JsonPatchException;
import com.google.common.collect.Iterables;


/**
 * JSON Patch {@code add} operation
 *
 * 

For this operation, {@code path} is the JSON Pointer where the value * should be added, and {@code value} is the value to add.

* *

Note that if the target value pointed to by {@code path} already exists, * it is replaced. In this case, {@code add} is equivalent to {@code replace}. *

* *

Note also that a value will be created at the target path if and only * if the immediate parent of that value exists (and is of the correct * type).

* *

Finally, if the last reference token of the JSON Pointer is {@code -} and * the immediate parent is an array, the given value is added at the end of the * array. For instance, applying:

* *
 *     { "op": "add", "path": "/-", "value": 3 }
 * 
* *

to:

* *
 *     [ 1, 2 ]
 * 
* *

will give:

* *
 *     [ 1, 2, 3 ]
 * 
*/ public final class AddOperation extends PathValueOperation { public static final String OPERATION_NAME = "add"; private static final ReferenceToken LAST_ARRAY_ELEMENT = ReferenceToken.fromRaw("-"); @JsonCreator public AddOperation(@JsonProperty("path") final JsonPointer path, @JsonProperty("value") final JsonNode value) { super(OPERATION_NAME, path, value); } @Override public JsonNode apply(final JsonNode node) throws JsonPatchException { if (getPath().isEmpty()) return value; /* * Check the parent node: it must exist and be a container (ie an array * or an object) for the add operation to work. */ final JsonNode parentNode = getPath().parent().path(node); if (parentNode.isMissingNode()) throw new JsonPatchException(BUNDLE.getMessage( "jsonPatch.noSuchParent")); if (!parentNode.isContainerNode()) throw new JsonPatchException(BUNDLE.getMessage( "jsonPatch.parentNotContainer")); return parentNode.isArray() ? addToArray(getPath(), node) : addToObject(getPath(), node); } private JsonNode addToArray(final JsonPointer path, final JsonNode node) throws JsonPatchException { final JsonNode ret = node.deepCopy(); final ArrayNode target = (ArrayNode) path.parent().get(ret); final TokenResolver token = Iterables.getLast(path); if (token.getToken().equals(LAST_ARRAY_ELEMENT)) { target.add(value); return ret; } final int size = target.size(); final int index; try { index = Integer.parseInt(token.toString()); } catch (final NumberFormatException ignored) { throw new JsonPatchException(BUNDLE.getMessage( "jsonPatch.notAnIndex")); } if (index < 0 || index > size) throw new JsonPatchException(BUNDLE.getMessage( "jsonPatch.noSuchIndex")); target.insert(index, value); return ret; } private JsonNode addToObject(final JsonPointer path, final JsonNode node) { final JsonNode ret = node.deepCopy(); final ObjectNode target = (ObjectNode) path.parent().get(ret); target.put(Iterables.getLast(path).getToken().getRaw(), value); return ret; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy