json
json copied to clipboard
Rel 3.11.2 -- patch method throw exception which use to work fine in Rel 3.9.1
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
- [ ] The bug also occurs if the latest version from the
develop
branch is used. - [ ] I can successfully compile and run the unit tests.
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
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" }
}