gear
gear

Reputation: 421

Universal way to copy json arrays to C++ vector (jsoncpp)

I found this soultion to convert any kind of iteratable (vector of bool's, vector of int's, etc.) to a json array, refering to this Post

template <typename iterable>
Json::Value iterable2json(iterable const& object) {
    Json::Value json_array;
    for (auto&& element : object) {
        json_array.append(element);
    }
    return json_array;
}

Since I am using vectors of ints, bools, floats etc. it is very helpful to simply pass the vector into the iterable2json function, to get an proper json array. Now I am trying to reverse this simple way, but only found this soultion, where I have to define wether the return value is a double/integer/bool etc.

void jsonarray2doublevector(Json::Value& json_array, std::vector<double>& vec) {

    vec.reserve(json_array.size());
    std::transform(json_array.begin(), json_array.end(), std::back_inserter(vec), [](const auto& e) { 
        return e.asDouble(); 
    });

}

This was the original Post from github

How can I simply pass any kind of vector to my function and determine the type? Like is it a vector of ints, or is it a vector of bools?

Upvotes: 0

Views: 2036

Answers (1)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122830

If its ok for the caller to decide what type of vector to transform to you can make the function a function template:

template <typename T>
void jsonarray2vector(Json::Value& json_array, std::vector<T>& vec) {

    vec.reserve(json_array.size());
    std::transform(json_array.begin(), json_array.end(), std::back_inserter(vec), [](const auto& e) { 
        return value_to_type<T>(e);
    });

Where value_to_type is a function template you need to specialize for the types you want to transform to. I am not aware of a simpler way to do that because Json::Value has only asXYZ() methods but no generic as<T>().

 // type for partial specializations
 template <typename To, typename From>
 struct value_to_type_impl;

 template <typename From>
 struct value_to_type_impl<double,From> {
       To operator()(const From& f) { return f.asDouble(); }
 }

 // ...and similar specializations for the other types

 // function to be called
 template <typename To,typename From>
 To value_to_type(const From& f) { return value_to_type<To,From>{}(f); }

You can then call it like this

Json::Value json_array;
std::vector<T> vec;
jsonarray2vector(json_array,vec);    

Since C++17 you can use constexpr if in combination with std::is_same to save some typing on the specializations. However, as getting a T from a Json::Value I would still suggest to stay with a value_to_type or similar for the conversion.

Upvotes: 2

Related Questions