Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rel 3.11.2 -- patch method throw exception which use to work fine in Rel 3.9.1 #4292

Open
2 tasks
sujayran opened this issue Feb 13, 2024 · 4 comments
Open
2 tasks

Comments

@sujayran
Copy link

sujayran commented Feb 13, 2024

Description

Code sample std::string valStr = jsonvalprofile.serialize();
nlohmann::json profileval = nlohmann::json::parse(valStr);

                             std::string valStr1 = jsonvalpatch.serialize();
                            nlohmann::json patchval = nlohmann::json::parse(valStr1);

                           // patch the original json value with patch object
                           result = profileval.patch(patchval);

Reproduction steps

sample json
{ "capacity": 50, "locality": "test", "id": "94f250ab-f6f5-46fa-8d38-765b5ce9ab6c", "xyz": [ { "lmn": "214", "nnp": "001" } ], "priority": 1 }

patch sample[ { "op" : "add", "path" : "/xyz/1/lmn", "value" : "214" }, { "op" : "add", "path" : "/xyz/1/nnp", "value" : "002" } ]

The patch operation fails with
[json.exception.out_of_range.401] array index 1 is out of range

Expected vs. actual results

Exapected:

patch to be successful as it use to happen in v3.9.1

Minimal code example

std::string valStr = jsonvalprofile.serialize();
                                nlohmann::json profileval = nlohmann::json::parse(valStr);

                                 std::string valStr1 = jsonvalpatch.serialize();
                                nlohmann::json patchval = nlohmann::json::parse(valStr1);

                               // patch the original json value with patch object
                               result = profileval.patch(patchval);

Error messages

The patch operation fails with 
 [json.exception.out_of_range.401] array index 1 is out of range

Compiler and operating system

clang --version clang version 15.0.7 (Fedora 15.0.7-2.fc37)

Library version

v3.11.2

Validation

@gregmarr
Copy link
Contributor

gregmarr commented Feb 14, 2024

Your sample JSON is invalid. It contains an unmatched ].

, } ], "xyz" : [ { "

Removing the }] makes it parsable.

@gregmarr
Copy link
Contributor

Your operation is invalid according to JSON Patch. Previous versions of the library erroneously accepted it. That was fixed in #3628

https://datatracker.ietf.org/doc/html/rfc6902#page-4

When the operation is applied, the target location MUST reference one of:

  • A member to add to an existing object - whereupon the supplied
    value is added to that object at the indicated location. If the
    member already exists, it is replaced by the specified value.
  • An element to add to an existing array - whereupon the supplied
    value is added to the array at the indicated location. Any
    elements at or above the specified index are shifted one position
    to the right. The specified index MUST NOT be greater than the
    number of elements in the array. If the "-" character is used to
    index the end of the array (see [RFC6901]), this has the effect of
    appending the value to the array.

Your location is neither an existing object, nor an array element, but instead a location inside a non-existing object. You need to add the full new element as a single operation, or add an empty element and then add members to it.

@sujayran
Copy link
Author

sujayran commented Feb 14, 2024

Thank for the reply, if i understand this right, you are saying its failing due to the fact that at location of array element 1 we don't have lmn "/xyz/1/lmn" ?

{
  "op" : "add",
  "path" : "/xyz/1",
  "value" : ""
}, {
  "op" : "add",
  "path" : "/xyz/1/lmn",
  "value" : "214"
}, {
  "op" : "add",
  "path" : "/xyz/1/nnp",
  "value" : "002"
} 

/usr/json-3.11.3/include/nlohmann/json.hpp:4799: auto nlohmann::basic_json<>::patch_inplace(const basic_json<> &)::(anonymous class)::operator()(json_pointer &, basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>) const [ObjectType = std::map, ArrayType = std::vector, StringType = std::basic_string, BooleanType = bool, NumberIntegerType = long, NumberUnsignedType = unsigned long, NumberFloatType = double, AllocatorType = std::allocator, JSONSerializer = nlohmann::adl_serializer, BinaryType = std::vector, CustomBaseClass = void]: Assertion `false' failed.

@gregmarr
Copy link
Contributor

gregmarr commented Feb 16, 2024

It's because /xyz/1 doesn't exist. You need to create /xyz/1 before you can add more things to it. What you have there is should be close to working but I think "value": "" would make it a string instead of an object. Can you try "value": {} instead?

Another way would be

{
  "op" : "add",
  "path" : "/xyz/1",
  "value" : { "lmn": "214", "nnp": "002" }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants