! @brief creates a diff as a JSON patch Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can be changed into the value @a target by calling @ref patch function. @invariant For two JSON values @a source and @a target, the following code yields always `true`: @code {.cpp} source.patch(diff(source, target)) == target;
| 24954 | @since version 2.0.0 |
| 24955 | */ |
| 24956 | JSON_HEDLEY_WARN_UNUSED_RESULT |
| 24957 | static basic_json diff(const basic_json& source, const basic_json& target, |
| 24958 | const std::string& path = "") |
| 24959 | { |
| 24960 | // the patch |
| 24961 | basic_json result(value_t::array); |
| 24962 | |
| 24963 | // if the values are the same, return empty patch |
| 24964 | if (source == target) |
| 24965 | { |
| 24966 | return result; |
| 24967 | } |
| 24968 | |
| 24969 | if (source.type() != target.type()) |
| 24970 | { |
| 24971 | // different types: replace value |
| 24972 | result.push_back( |
| 24973 | { |
| 24974 | {"op", "replace"}, {"path", path}, {"value", target} |
| 24975 | }); |
| 24976 | return result; |
| 24977 | } |
| 24978 | |
| 24979 | switch (source.type()) |
| 24980 | { |
| 24981 | case value_t::array: |
| 24982 | { |
| 24983 | // first pass: traverse common elements |
| 24984 | std::size_t i = 0; |
| 24985 | while (i < source.size() && i < target.size()) |
| 24986 | { |
| 24987 | // recursive call to compare array values at index i |
| 24988 | auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); |
| 24989 | result.insert(result.end(), temp_diff.begin(), temp_diff.end()); |
| 24990 | ++i; |
| 24991 | } |
| 24992 | |
| 24993 | // i now reached the end of at least one array |
| 24994 | // in a second pass, traverse the remaining elements |
| 24995 | |
| 24996 | // remove my remaining elements |
| 24997 | const auto end_index = static_cast<difference_type>(result.size()); |
| 24998 | while (i < source.size()) |
| 24999 | { |
| 25000 | // add operations in reverse order to avoid invalid |
| 25001 | // indices |
| 25002 | result.insert(result.begin() + end_index, object( |
| 25003 | { |
| 25004 | {"op", "remove"}, |
| 25005 | {"path", path + "/" + std::to_string(i)} |
| 25006 | })); |
| 25007 | ++i; |
| 25008 | } |
| 25009 | |
| 25010 | // add other remaining elements |
| 25011 | while (i < target.size()) |
| 25012 | { |
| 25013 | result.push_back( |