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

to_json for pairs, tuples #614

Closed
hsdk123 opened this issue Jun 10, 2017 · 14 comments
Closed

to_json for pairs, tuples #614

hsdk123 opened this issue Jun 10, 2017 · 14 comments
Assignees
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Milestone

Comments

@hsdk123
Copy link

hsdk123 commented Jun 10, 2017

Hi, I was wondering if there might be a simple way to to_json() pairs and tuples, instead of having to explicitly create each element for json.

@nlohmann
Copy link
Owner

I'm not sure what you mean. Could you provide more details or an example please?

@hsdk123
Copy link
Author

hsdk123 commented Jun 11, 2017

Thanks for the reply! For example, let's say i want to encode an std::pair<int, int> into json.
Ideally:

struct Person
{
    std::pair<int, int> position
};
	void to_json( json& j, const Person& d )
	{
		j = json{
			{ "position", d.position }
		};
	}
	void from_json( const json& j, Person& d )
	{
		d.position= j.at( "position" ).get<std::pair<int, int>>();
	}

But sadly this gives an error.
Instead, I have to encode each element of the pair (or tuple) explicitly as a different json element, which can get slightly troublesome.

Hopefully I've just misunderstood something and there is a direct method, otherwise it would be absolutely great to be able to do this.

@gregmarr
Copy link
Contributor

gregmarr commented Jun 11, 2017

Have you tried something like this? (I'm not sure if it will work, just speculating)

void to_json( json& j, const Person& d )
{
	to_json(j["position"], d.position);
}
void from_json( const json& j, lvn::NTextbox::NChar::Data& d )
{
	from_json(j["position"], d.position);
}

@nlohmann
Copy link
Owner

There is no default conversion between json and std::pair. You need to provide translations from/to arrays. This would work:

#include "json.hpp"

using json = nlohmann::json;

struct Person
{
    std::pair<int, int> position;
};

void to_json( json& j, const Person& d )
{
    // encode pair as a list
    j = json{ { "position", {d.position.first, d.position.second} } };
}

void from_json( const json& j, Person& d )
{
    auto& pos = j.at("position");
    // decode list as pair
    d.position = std::make_pair(pos[0], pos[1]);
}

int main()
{
    // create a person
    Person p;
    p.position = {17, 42};
    
    // person -> json
    json j = p;
    std::cout << std::setw(2) << j << std::endl;
    
    // json -> person
    Person p2 = j;
    std::cout << std::boolalpha << (p.position == p2.position) << std::endl;
}

@nlohmann nlohmann added kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation labels Jun 11, 2017
@theodelrieu
Copy link
Contributor

I added support for std::pair in a recent PR, however it requires the .first to be a compatible string type , so it can represent the combination of a string field, and a JSON object.

I didn't think about representing pairs as arrays (e.g. std::pair<int, int>), this should be discussed, and we might need to revert my PR.

@gregmarr
Copy link
Contributor

In my own codebase, I have a function that encodes them as an object withfirst and second members.

@nlohmann
Copy link
Owner

I think encoding pairs and tuples as JSON arrays could be a good idea. However, I am not sure about std::pair<std::string, X> in this context. I think a single pair should not be encoded as JSON object.

@theodelrieu
Copy link
Contributor

Since almost any to_json method provided by the library can be overwritten, we could provide a reasonable default for std::pair.

Fixing #600 while staying generic-friendly in the implementation of to_json(CompatibleObjectType) is quite hard, especially if we need to rely on CompatibleObjectType::value_type...

I don't really know what to do with this std::pair problem

@theodelrieu
Copy link
Contributor

I think you're right, we should convert pairs and tuples as arrays, element ordering being mandatory for those.

People with custom conversions with std::pair (like @gregmarr) won't be impacted by this change anyway.

@nlohmann
Copy link
Owner

Exactly. I wanted to write the same. I think it is a good and predictable behavior to use arrays.

@theodelrieu
Copy link
Contributor

Ok, I have (finally) some time to work on the library, I'm starting to implement this. I will then try to extract some nested classes as we discussed in #474.

@nlohmann
Copy link
Owner

Great. #458 shows some challenges when it comes to parsing. Some restructuring of the code may help here.

@gregmarr
Copy link
Contributor

I wouldn't be affected anyway, as my functions were written before to_json and from_json were added to the library and thus are completely outside the library.

@nlohmann
Copy link
Owner

With #624, the library now also supports the conversion from/to std::pair, std::tuple, and std::array.

@nlohmann nlohmann self-assigned this Jun 19, 2017
@nlohmann nlohmann added this to the Release 3.0.0 milestone Jun 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

4 participants