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

Cannot convert from json array to std::array #553

Closed
wgtdkp opened this issue Apr 13, 2017 · 5 comments
Closed

Cannot convert from json array to std::array #553

wgtdkp opened this issue Apr 13, 2017 · 5 comments
Assignees
Labels
kind: enhancement/improvement solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Milestone

Comments

@wgtdkp
Copy link

wgtdkp commented Apr 13, 2017

Conversion from std::array to json array works well, but not in reverse.

std::string r = R"([1, 2, 3, 4])";
std::array<int, 4> arr = json::parse(r);

clang++ gives compiling errors:

/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_iterator.h:661:20: error: 
      no member named 'insert' in 'std::array<int, 4>'
        iter = container->insert(iter, std::move(__value));
               ~~~~~~~~~  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_algo.h:4175:12: note: 
      in instantiation of member function 'std::insert_iterator<std::array<int, 4> >::operator='
      requested here
        *__result = __unary_op(*__first);
                  ^
../../src/json.hpp:720:10: note: in instantiation of function template specialization
      'std::transform<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char>, bool,
      long, unsigned long, double, std::allocator, adl_serializer>::iter_impl<const
      nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char>, bool, long, unsigned
      long, double, std::allocator, adl_serializer> >, std::insert_iterator<std::array<int, 4> >, (lambda
      at ../../src/json.hpp:721:50)>' requested here
    std::transform(j.begin(), j.end(),
         ^
../../src/json.hpp:804:5: note: in instantiation of function template specialization
      'nlohmann::detail::from_json_array_impl<nlohmann::basic_json<std::map, std::vector,
      std::__cxx11::basic_string<char>, bool, long, unsigned long, double, std::allocator,
      adl_serializer>, std::array<int, 4> >' requested here
    from_json_array_impl(j, arr, priority_tag<1> {});
    ^
../../src/json.hpp:902:16: note: in instantiation of function template specialization
      'nlohmann::detail::from_json<nlohmann::basic_json<std::map, std::vector,
      std::__cxx11::basic_string<char>, bool, long, unsigned long, double, std::allocator,
      adl_serializer>, std::array<int, 4>, 0>' requested here
        return from_json(j, val);
               ^
../../src/json.hpp:917:16: note: in instantiation of function template specialization
      'nlohmann::detail::from_json_fn::call<nlohmann::basic_json<std::map, std::vector,
      std::__cxx11::basic_string<char>, bool, long, unsigned long, double, std::allocator,
      adl_serializer>, std::array<int, 4> >' requested here
        return call(j, val, priority_tag<1> {});
               ^
../../src/json.hpp:964:9: note: in instantiation of function template specialization
      'nlohmann::detail::from_json_fn::operator()<nlohmann::basic_json<std::map, std::vector,
      std::__cxx11::basic_string<char>, bool, long, unsigned long, double, std::allocator,
      adl_serializer>, std::array<int, 4> >' requested here
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
        ^
../../src/json.hpp:3272:36: note: in instantiation of function template specialization
      'nlohmann::adl_serializer<std::array<int, 4>, void>::from_json<const nlohmann::basic_json<std::map,
      std::vector, std::__cxx11::basic_string<char>, bool, long, unsigned long, double, std::allocator,
      adl_serializer> &, std::array<int, 4> >' requested here
        JSONSerializer<ValueType>::from_json(*this, ret);
                                   ^
../../src/json.hpp:3530:16: note: in instantiation of function template specialization
      'nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char>, bool, long, unsigned
      long, double, std::allocator, adl_serializer>::get<std::array<int, 4>, std::array<int, 4>, 0>'
      requested here
        return get<ValueType>();
               ^
array.cc:8:28: note: in instantiation of function template specialization 'nlohmann::basic_json<std::map,
      std::vector, std::__cxx11::basic_string<char>, bool, long, unsigned long, double, std::allocator,
      adl_serializer>::operator array<std::array<int, 4>, 0>' requested here
  std::array<int, 4> arr = json::parse(r);
                           ^
1 error generated.

It seems we use std::inserter to transform json array to std::array, but std::array doesn't support insertion.
Is it designed so?
It seems unreasonable if we can convert std::array to json array but cannot do the same in reverse(and this could be easily supported, isn't it?).

My environment:

  1. clang++ = 3.8.0
  2. ubuntu = 16.04
  3. linux kernel = 4.4.0
@gregmarr
Copy link
Contributor

gregmarr commented Apr 13, 2017

Not to say that it can't be done, but the hardest parts of this are that std::array is statically sized and typed, while json is dynamically sized and types. What should happen if the array sizes and types don't match at runtime? There's no problem going in the other direction, because the dynamically sized and typed object can take in the statically sized and typed object.

Assuming that you know that the size of the json object is correct, you can do something like this:

std::string r = R"([1, 2, 3, 4])";
auto j = json::parse(r);
std::array<int, 4> arr = {j[0], j[1], j[2], j[3]}

but it's probably better to do something like this:

std::string r = R"([1, 2, 3, 4])";
std::array<int, 4> arr;
populateArrayFromJsonString(arr, r);

template<typename T, int N> void populateArrayFromJsonString(std::array<T, N> &arr, std::string const &r)
{
    auto j = json::parse(r);
    // TODO: Check that j is an array of size N
    for(int i = 0; i < N; ++i)
    {
        // TODO check that j[i] is of type T
        arr[i] = j.get<T>(i);
    }
}

(All code here was written here and not compiled or tested.)

@wgtdkp
Copy link
Author

wgtdkp commented Apr 13, 2017

I think it's the user's responsibility to make sure the sizes of json array and std::array are matched. Besides, we can do more in function from_json_array_impl to make the conversion safe:

std::transform(j.begin(), j.begin() + std::min(N, j.size()), begin(arr), [](const BasicJsonType & i) {
    // get<BasicJsonType>() returns *this, this won't call a from_json
    // method when value_type is BasicJsonType
    return i.template get<typename std::array<T, N>::value_type>();
});

@nlohmann nlohmann added the solution: wontfix the issue will not be fixed (either it is impossible or deemed out of scope) label May 3, 2017
@nlohmann
Copy link
Owner

nlohmann commented May 3, 2017

I think we should not address this.

@nlohmann nlohmann closed this as completed May 3, 2017
This was referenced Jun 17, 2017
@nlohmann
Copy link
Owner

In #625, we address std::tuple which is very related to an std::array. We may treat them equally.

@nlohmann nlohmann reopened this Jun 19, 2017
@nlohmann
Copy link
Owner

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

@nlohmann nlohmann added kind: enhancement/improvement solution: proposed fix a fix for the issue has been proposed and waits for confirmation and removed solution: wontfix the issue will not be fixed (either it is impossible or deemed out of scope) labels Jun 19, 2017
@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: 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

3 participants