nlohmann / json

JSON for Modern C++

Home Page:https://json.nlohmann.me

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

sujayran opened this issue · comments

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

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

, } ], "xyz" : [ { "

Removing the }] makes it parsable.

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.

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.

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