nlohmann / json

JSON for Modern C++
https://json.nlohmann.me
MIT License
41.3k stars 6.58k forks source link

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

Open sujayran opened 4 months ago

sujayran commented 4 months ago

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 commented 4 months ago

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

, } ], "xyz" : [ { "

Removing the }] makes it parsable.

gregmarr commented 4 months ago

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:

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 commented 4 months ago

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 commented 4 months ago

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" }
}