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

json Conversions to/from C++ objects #223

Closed
JoeStroupe opened this issue Aug 28, 2020 · 33 comments
Closed

json Conversions to/from C++ objects #223

JoeStroupe opened this issue Aug 28, 2020 · 33 comments

Comments

@JoeStroupe
Copy link

Does Boost.json support conversions from C++ objects to json, and from json to C++ objects? Use case is in the interface between C++ application and calls to the ArangoDB HTTP REST API. I'm using libcurl to generate REST calls (with json bodies) into ArangoDB, and I need to convert C++ object members and their values to json for those calls. Then, on the return route, I need to populate C++ object members with the json data returned from ArangoDB calls. I also need to know if such conversions can be done recursively, or only singly.

What of the case where my C++ objects exist in a vector or other std container? I'm looking for functionality akin to that noted here: https://stackoverflow.com/questions/17549906/c-json-serialization

Scroll down to the solution with 85 votes, posted by Guillaume Racicot.

@sdkrystian
Copy link
Member

The library supports conversions to and from user-defined types via value_to<T>(expr) and value_from(expr). Generic conversions for container types can be done by the library out of the box so long as they fit a certain "container-like" criteria, and such conversions are performed recursively. You can find some more details of what is supported here: http://vinniefalco.github.io/doc/json/json/usage/conversion.html

If the generic conversions that we provide aren't enough, you can implement the conversion yourself by providing overloads for tag_invoke. These will be found by ADL and value_to/from will use them for the conversion.

@vinniefalco
Copy link
Member

vinniefalco commented Aug 28, 2020

Short answer: Yes (http://vinniefalco.github.io/doc/json/json/usage/conversion.html)

Long answer:

Given a user defined type T:

    T t;
    ...
    // Convert from T to json::value
    json::value jv = json::value_from( t );

    // Convert json::value to T
    T t2 = json::value_to( jv );

This is accomplished by providing overloads of tag_invoke for T in the namespace of T:

    // Called to convert json::value to T
    T tag_invoke( json::value_to_tag<T>, json::value const& jv );

    // Called to convert T to json::value
    void tag_invoke( json::value_from_tag, json::value& jv, T const& );

Furthermore as @sdkrystian noted, the library provides generic conversions for ranges, which handles std::vector<T> (and maps with key/value pairs).

@JoeStroupe
Copy link
Author

JoeStroupe commented Aug 28, 2020 via email

@JoeStroupe
Copy link
Author

JoeStroupe commented Aug 28, 2020 via email

@JoeStroupe
Copy link
Author

JoeStroupe commented Aug 28, 2020 via email

@vinniefalco
Copy link
Member

I want to build the json lib as MD/d

The easiest thing to do is ignore my CMakeLists.txt and just add src.cpp to your project:
https://github.com/CPPAlliance/json/blob/397a31f1667150a94c1b079de83bec85065729f6/src/src.cpp

Alternatively, just add the following line to any one of your translation units:

#include <boost/json/src.hpp>

@JoeStroupe
Copy link
Author

JoeStroupe commented Aug 28, 2020 via email

@vinniefalco
Copy link
Member

Looks like this is resolved, thanks!

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 1, 2020 via email

@vinniefalco
Copy link
Member

If you would be willing to critique it, what is your preferred way for me to get you the code and explanation of what I’m trying to do?

I am more than happy to comment on the usage of my libraries in other programs. The best way to do that is to open a pull request against your own GitHub repository, and add me as a reviewer so I can leave comments.

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 1, 2020 via email

@vinniefalco
Copy link
Member

But when I’m ready I could send you a zip file with the code and a good explanation of what I’m trying/needing to accomplish.

I encourage you to create a repository. It is easy, and free. I can't really comment on a zip file. GitHub has wonderful tools for collaboration - we should use it!

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 1, 2020 via email

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 8, 2020 via email

@vinniefalco
Copy link
Member

vinniefalco commented Sep 8, 2020

I just recently changed to_string to serialize. Have you picked up the latest develop branch?

When I use to_string() I get a string with ‘[‘ ‘]’ brkts and it’s not suitable for a json body in an HTTP request.

Yeah...that's the problem. The standard library and Boost already provide many overloads of to_string so even though I took out the function, another overload is still being found! So it is being converted incorrectly...

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 8, 2020 via email

@vinniefalco
Copy link
Member

Any suggestions on how to get the new serialize() to work correctly?

Can you please provide a small sample program that demonstrates the problem?

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 8, 2020 via email

@vinniefalco
Copy link
Member

I don't see any zip file, can you paste the minimal sample program here?

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 8, 2020 via email

@vinniefalco
Copy link
Member

can you please reduce that down to a small program, with main, of just a few lines, that reproduces the problem? In other words a minimal reproducible example.

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 8, 2020 via email

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 8, 2020 via email

@vinniefalco
Copy link
Member

Your program works fine for me, I get this output
image

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 8, 2020 via email

@vinniefalco
Copy link
Member

jval = { t->name + CURL_PAIR_SEPARATOR + t->value };

Well, what you are doing here is creating an array of one-element arrays each containing a string. If you want an object with key/value pairs then you need something resembling a map. This is one way to do it:

int main()
{
    std::map<std::string, std::string> ReqV;
    ReqV.emplace( "Hello", "World" );
    ReqV.emplace( "Goodbye", "World" );
    value requestBodyjs = boost::json::value_from(ReqV);
    std::string str = boost::json::serialize(requestBodyjs);
    std::cout << str << std::endl;
    return 0;
}

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 8, 2020 via email

@vinniefalco
Copy link
Member

there’s a stinking bug in VS 2015

Try boost::container::map

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 9, 2020 via email

@vinniefalco
Copy link
Member

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 9, 2020 via email

@vinniefalco
Copy link
Member

You are including src.hpp which is required for linking, but you are not including the headers which give you all the declarations:

#Include <boost/json.hpp>

Alternatively you can include just what you need:

#Include <boost/json/value_to.hpp>
#Include <boost/json/value_from.hpp>

@JoeStroupe
Copy link
Author

JoeStroupe commented Sep 9, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants