jakartaee / jsonp-api

Jakarta JSON Processing
https://eclipse.org/ee4j/jsonp
Other
139 stars 59 forks source link

When calling PATCH with operation "op":"replace" for null value, exception is thrown: jakarta.json.JsonException: Non-existing name/value pair in the object for key #325

Closed gterseglav closed 2 years ago

gterseglav commented 2 years ago

If you execute jsonPatch.apply() using operation "op":"replace", where you try to replace null attribute with new value, exception is thrown; jakarta.json.JsonException: Non-existing name/value pair in the object for key

Pseudo code Json object:

{
  "postName": "PostName1",
  "postCode": null
}

Pseudo code patch object:

[
  {
    "op":"replace"
    "path":"/postCode"
    "value":1000
  }
]

Example code block:

        try {
            JsonObject individualJsonObject = reader.readObject();
            patchedIndividualJsonObject = jsonPatch.apply(individualJsonObject);
        } catch (JsonException e) {
            logger.error("JSonPatch could not be applied to the object: Id={}, jsonPatch={}", id, jsonPatch, e);
            logger.error("individualJson={}", individualJson);
            throw new Exception(...);
        }

Maven dependency:

    <dependency>
      <groupId>org.glassfish</groupId>
      <artifactId>jakarta.json</artifactId>
      <version>2.0.1</version>
    </dependency>

Json patch RFC 6902: According to Json patch RFC 6902: 4.3. replace The "replace" operation replaces the value at the target location with a new value. The operation object MUST contain a "value" member whose content specifies the replacement value.

The target location MUST exist for the operation to be successful.

For example:

{ "op": "replace", "path": "/a/b/c", "value": 42 }

This operation is functionally identical to a "remove" operation for a value, followed immediately by an "add" operation at the same location with the replacement value.

There is no limitation that existing value should be null so it seems this behavior is a bug.

Workaround: When executing patch for null attribute values, use "op":"add" instead of "op":"replace".

gterseglav commented 2 years ago

Additional comment after specification analysis: 4.3. replace states that: 1) object must exist: The target location MUST exist for the operation to be successful. 2) replace is combo of remove and add:

This operation is functionally identical to a "remove" operation for
a value, followed immediately by an "add" operation at the same
location with the replacement value.

If I then go to the definition of 4.2. remove

The "remove" operation removes the value at the target location.

The target location MUST exist for the operation to be successful.

Altenative conclusion: If I understand correctly, this means that input json object, that is missing some field value, doesn't meet the condition that target location exists.

When we add operation "op":"replace" to json patch, logic for "op":"remove" is called.

Logic checks whether path /postCode exists. Because postCode is null this means that it is not added to input json object and target doesn't exist.

Throwing an exception is correct way of handling such situation. In this case implementation is done according to spec and this bug is invalid.

Thanks for detailed clarifications.

gterseglav commented 2 years ago

Using unit test examples it is clear that the jakarta json library works in the following way:

Based on this analysis I conclude that implementation works according to RFC6902, because it throws exception only when the following condition is not met: The target location MUST exist for the operation to be successful.

I am closing this bug as invalid.