boostorg / json

A C++11 library for parsing and serializing JSON to and from a DOM container in memory.
https://boost.org/libs/json
Boost Software License 1.0
424 stars 94 forks source link

Add a convenience member function to call value_to #983

Open kiwixz opened 5 months ago

kiwixz commented 5 months ago

Hi, first of all thanks for the great library fast yet easy to use.

I'm currently writing tag_invoke functions to convert JSON values from/to a class, and I have something like this:

MyClass{json.at("superint1").to_number<int>(),
        json.at("superint2").to_number<int>(),
        json.at("superbool").as_bool(),
        json.at("superstring").as_string(),
        boost::json::value_to<std::vector<int>>(json.at("supervectorofint"))}

It's a class with private values and a constructor, so I cant just rely on Boost Describe for this.

If there was a to<T>() member function (just calling boost::json::value_to under the hood), I could have arguably more consistent code:

MyClass{json.at("superint1").to_number<int>(),
        json.at("superint2").to_number<int>(),
        json.at("superbool").as_bool(),
        json.at("superstring").as_string(),
        json.at("supervectorofint").to<std::vector<int>>()}

And it could also allow something ever better (to my eyes that is!):

MyClass{json.at("superint1").to<int>(),
        json.at("superint2").to<int>(),
        json.at("superbool").to<bool>(),
        json.at("superstring").to<std::string>(),
        json.at("supervectorofint").to<std::vector<int>>()}

I like the fact that there is a fixed set of as_* functions, guaranteeing direct access to the underlying value; but value_to seems to be the "do whatever you need but get me this" convenience method I usually want.

Related to #418.

pdimov commented 5 months ago

You can still use Describe if you declare an intermediate struct holding the parameters.

pdimov commented 5 months ago

On second thought, isn't

MyClass{json.at("superint1").to<int>(),
        json.at("superint2").to<int>(),
        json.at("superbool").to<bool>(),
        json.at("superstring").to<std::string>(),
        json.at("supervectorofint").to<std::vector<int>>()}

possible to write today as

MyClass{
        value_to<int>(json.at("superint1")),
        value_to<int>(json.at("superint2")),
        value_to<bool>(json.at("superbool")),
        value_to<std::string>(json.at("superstring")),
        value_to<std::vector<int>>(json.at("supervectorofint"))
}

?

grisumbras commented 5 months ago

It is. I think, @kiwixz considers that syntax too cumbersome.

To be honest, I'm not fond of adding just another way to call value_to.

kiwixz commented 5 months ago

I didn't think of using namespace here which helps a lot.

It still feels weird to me to use it as a free function, especially when we have to_number as a member.

grisumbras commented 5 months ago

True, but making an equivalent of value_to member function of value is much more intrusive.