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

is it possible merge two json object #428

Closed
itviewer opened this issue Jan 15, 2017 · 14 comments
Closed

is it possible merge two json object #428

itviewer opened this issue Jan 15, 2017 · 14 comments
Assignees
Labels
kind: enhancement/improvement solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Milestone

Comments

@itviewer
Copy link

some function like this
json1.join(json2) or
json1.merge(json2) or
json1 += json2

@nlohmann
Copy link
Owner

This is an interesting question. Currently, there is no insert(InputIt first, InputIt last) function such as std::map::insert.

@nlohmann
Copy link
Owner

(I should definitely have another look at all the overloads of insert of the STL containers. For instance, std::map::iterator insert( const_iterator hint, const value_type& value ); exists, but an insert function with the same signature is currently only allowed for arrays.)

@andnp
Copy link

andnp commented Mar 23, 2017

I have also needed this type of functionality. For the time being until this is closed, I have been using this code which modifies the json object in place.

One thing to consider is the desired behavior when j1 and j2 have matching keys. In this case j1 is over-written by values in j2.

Hopefully this helps for now.

void extendJson(json &j1, const json &j2) {
    for (const auto &j : json::iterator_wrapper(j2)) {
        j1[j.key()] = j.value();
    }
}

@nlohmann
Copy link
Owner

Thanks for the hint. I shall have a look at the insert functions of the STL containers and propose an extension here.

@nlohmann nlohmann modified the milestones: Release 3.0.0, Release 3.0.1 Mar 24, 2017
@nlohmann nlohmann self-assigned this Mar 24, 2017
nlohmann added a commit that referenced this issue Apr 7, 2017
This implementation forwards the iterators to std::map::insert.
@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Apr 7, 2017
@nlohmann
Copy link
Owner

nlohmann commented Apr 7, 2017

Here is a proposal for an insert function that takes an iterator range and can merge an object into another: 97a25de. Feedback very appreciated!

@AraHaan
Copy link

AraHaan commented Apr 8, 2017

Well in python it interprets json data as an dict and then it could append (or insert) . In that case append is an alias of insert that would append to the end of the json, but insert would allow you to specify where to insert entries at. Maybe this library could copy some of that logic even though it would not be an dict.

I would prefer an shortcut that would overload operator>> where if it is another json object it would move the data over to the other one and return the object with it merged so when someone does this.

json2 >> json1;

That json2's data would move to json1 (or so it would seem like it).

@nlohmann
Copy link
Owner

nlohmann commented Apr 8, 2017

@AraHaan What exactly do you propose? We have several overloads for push_back and insert. And Python only interprets JSON objects as dict. Arrays are mapped to lists.

@nlohmann
Copy link
Owner

nlohmann commented Apr 8, 2017

@AraHaan I fear that overload of operator>> would be very unintuitive for C++ programmers.

@itviewer
Copy link
Author

Thanks,It's good for me!

@nlohmann
Copy link
Owner

Merged with 4b316ec.

@mlund
Copy link

mlund commented Jul 3, 2017

Great this has been added; #252 addresses a similar issue and I have used

json merge( const json &a, const json &b )
{
    json result = a.flatten();
    json tmp = b.flatten();
    for ( auto it = tmp.begin(); it != tmp.end(); ++it )
        result[it.key()] = it.value();
    return result.unflatten();
}

I found the scenario below slightly counter-intuitive using the new approach,

json j1 = { {"a",1} };
json j2 = { {"a",2} };
j1.insert(j2.begin(), j2.end()); // --> a=1

But perhaps this is also the behaviour of maps?

@mlund
Copy link

mlund commented Jul 3, 2017

std::map::insert does not overwrite either.

@nlohmann
Copy link
Owner

nlohmann commented Jul 3, 2017

We use std::map::insert internally to provide the least surprising behavior. I also would have needed to look up the behavior in case of a duplicate.

@mlund
Copy link

mlund commented Jul 3, 2017

That makes sense. I think the solution is simply to pay attention to order when merging,

std::map<int, int> goodKeys;
std::map<int, int> betterKeys;
betterKeys.insert(goodKeys.begin(), goodKeys.end());

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: enhancement/improvement solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

5 participants