🐛 re-added support for std::valarray #702
This commit is contained in:
		
							parent
							
								
									41b2c69bdb
								
							
						
					
					
						commit
						9fd031b6f4
					
				
					 4 changed files with 113 additions and 5 deletions
				
			
		
							
								
								
									
										46
									
								
								src/json.hpp
									
										
									
									
									
								
							
							
						
						
									
										46
									
								
								src/json.hpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -54,6 +54,7 @@ SOFTWARE.
 | 
			
		|||
#include <string> // getline, stoi, string, to_string
 | 
			
		||||
#include <type_traits> // add_pointer, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type
 | 
			
		||||
#include <utility> // declval, forward, make_pair, move, pair, swap
 | 
			
		||||
#include <valarray> // valarray
 | 
			
		||||
#include <vector> // vector
 | 
			
		||||
 | 
			
		||||
// exclude unsupported compilers
 | 
			
		||||
| 
						 | 
				
			
			@ -661,6 +662,18 @@ struct external_constructor<value_t::array>
 | 
			
		|||
        }
 | 
			
		||||
        j.assert_invariant();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename BasicJsonType, typename T,
 | 
			
		||||
             enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
 | 
			
		||||
    static void construct(BasicJsonType& j, const std::valarray<T>& arr)
 | 
			
		||||
    {
 | 
			
		||||
        using std::begin;
 | 
			
		||||
        using std::end;
 | 
			
		||||
        j.m_type = value_t::array;
 | 
			
		||||
        j.m_value = value_t::array;
 | 
			
		||||
        j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
 | 
			
		||||
        j.assert_invariant();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
| 
						 | 
				
			
			@ -921,11 +934,18 @@ template <
 | 
			
		|||
        is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
 | 
			
		||||
        std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
 | 
			
		||||
        int > = 0 >
 | 
			
		||||
void to_json(BasicJsonType& j, const  CompatibleArrayType& arr)
 | 
			
		||||
void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
 | 
			
		||||
{
 | 
			
		||||
    external_constructor<value_t::array>::construct(j, arr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename BasicJsonType, typename T,
 | 
			
		||||
          enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
 | 
			
		||||
void to_json(BasicJsonType& j, std::valarray<T> arr)
 | 
			
		||||
{
 | 
			
		||||
    external_constructor<value_t::array>::construct(j, std::move(arr));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename BasicJsonType>
 | 
			
		||||
void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -936,7 +956,7 @@ template <
 | 
			
		|||
    typename BasicJsonType, typename CompatibleObjectType,
 | 
			
		||||
    enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
 | 
			
		||||
                int> = 0 >
 | 
			
		||||
void to_json(BasicJsonType& j, const  CompatibleObjectType& obj)
 | 
			
		||||
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
 | 
			
		||||
{
 | 
			
		||||
    external_constructor<value_t::object>::construct(j, obj);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1082,6 +1102,22 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
 | 
			
		|||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// valarray doesn't have an insert method
 | 
			
		||||
template<typename BasicJsonType, typename T,
 | 
			
		||||
         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
 | 
			
		||||
void from_json(const BasicJsonType& j, std::valarray<T>& l)
 | 
			
		||||
{
 | 
			
		||||
    if (JSON_UNLIKELY(not j.is_array()))
 | 
			
		||||
    {
 | 
			
		||||
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
 | 
			
		||||
    }
 | 
			
		||||
    l.resize(j.size());
 | 
			
		||||
    for (size_t i = 0; i < j.size(); ++i)
 | 
			
		||||
    {
 | 
			
		||||
        l[i] = j[i];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename BasicJsonType, typename CompatibleArrayType>
 | 
			
		||||
void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -4441,7 +4477,7 @@ class binary_reader
 | 
			
		|||
    */
 | 
			
		||||
    BasicJsonType parse_msgpack(const bool strict)
 | 
			
		||||
    {
 | 
			
		||||
        const auto res =  parse_msgpack_internal();
 | 
			
		||||
        const auto res = parse_msgpack_internal();
 | 
			
		||||
        if (strict)
 | 
			
		||||
        {
 | 
			
		||||
            get();
 | 
			
		||||
| 
						 | 
				
			
			@ -13187,7 +13223,7 @@ class basic_json
 | 
			
		|||
    */
 | 
			
		||||
    template<typename A1, typename A2,
 | 
			
		||||
             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
 | 
			
		||||
    static basic_json from_cbor(A1&& a1, A2&& a2, const bool strict = true)
 | 
			
		||||
    static basic_json from_cbor(A1 && a1, A2 && a2, const bool strict = true)
 | 
			
		||||
    {
 | 
			
		||||
        return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_cbor(strict);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -13274,7 +13310,7 @@ class basic_json
 | 
			
		|||
    */
 | 
			
		||||
    template<typename A1, typename A2,
 | 
			
		||||
             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
 | 
			
		||||
    static basic_json from_msgpack(A1&& a1, A2&& a2, const bool strict = true)
 | 
			
		||||
    static basic_json from_msgpack(A1 && a1, A2 && a2, const bool strict = true)
 | 
			
		||||
    {
 | 
			
		||||
        return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_msgpack(strict);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,6 +38,7 @@ using nlohmann::json;
 | 
			
		|||
#include <list>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <unordered_set>
 | 
			
		||||
#include <valarray>
 | 
			
		||||
 | 
			
		||||
TEST_CASE("constructors")
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -311,6 +312,36 @@ TEST_CASE("constructors")
 | 
			
		|||
            CHECK(a2 == a);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("std::valarray<int>")
 | 
			
		||||
        {
 | 
			
		||||
            std::valarray<int> va = {1, 2, 3, 4, 5};
 | 
			
		||||
            json j(va);
 | 
			
		||||
            CHECK(j.type() == json::value_t::array);
 | 
			
		||||
            CHECK(j == json({1, 2, 3, 4, 5}));
 | 
			
		||||
 | 
			
		||||
            std::valarray<int> jva = j;
 | 
			
		||||
            CHECK(jva.size() == va.size());
 | 
			
		||||
            for (size_t i = 0; i < jva.size(); ++i)
 | 
			
		||||
            {
 | 
			
		||||
                CHECK(va[i] == jva[i]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("std::valarray<double>")
 | 
			
		||||
        {
 | 
			
		||||
            std::valarray<double> va = {1.2, 2.3, 3.4, 4.5, 5.6};
 | 
			
		||||
            json j(va);
 | 
			
		||||
            CHECK(j.type() == json::value_t::array);
 | 
			
		||||
            CHECK(j == json({1.2, 2.3, 3.4, 4.5, 5.6}));
 | 
			
		||||
 | 
			
		||||
            std::valarray<double> jva = j;
 | 
			
		||||
            CHECK(jva.size() == va.size());
 | 
			
		||||
            for (size_t i = 0; i < jva.size(); ++i)
 | 
			
		||||
            {
 | 
			
		||||
                CHECK(va[i] == jva[i]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("std::vector<json>")
 | 
			
		||||
        {
 | 
			
		||||
            std::vector<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,7 @@ using nlohmann::json;
 | 
			
		|||
#include <list>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <unordered_set>
 | 
			
		||||
#include <valarray>
 | 
			
		||||
 | 
			
		||||
TEST_CASE("value conversion")
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1008,6 +1009,15 @@ TEST_CASE("value conversion")
 | 
			
		|||
                auto m5 = j5.get<std::forward_list<std::string>>();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("std::valarray")
 | 
			
		||||
            {
 | 
			
		||||
                auto m1 = j1.get<std::valarray<int>>();
 | 
			
		||||
                auto m2 = j2.get<std::valarray<unsigned int>>();
 | 
			
		||||
                auto m3 = j3.get<std::valarray<double>>();
 | 
			
		||||
                auto m4 = j4.get<std::valarray<bool>>();
 | 
			
		||||
                auto m5 = j5.get<std::valarray<std::string>>();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("std::vector")
 | 
			
		||||
            {
 | 
			
		||||
                auto m1 = j1.get<std::vector<int>>();
 | 
			
		||||
| 
						 | 
				
			
			@ -1050,6 +1060,7 @@ TEST_CASE("value conversion")
 | 
			
		|||
                CHECK_THROWS_AS((json().get<std::vector<int>>()), json::type_error&);
 | 
			
		||||
                CHECK_THROWS_AS((json().get<std::vector<json>>()), json::type_error&);
 | 
			
		||||
                CHECK_THROWS_AS((json().get<std::list<json>>()), json::type_error&);
 | 
			
		||||
                CHECK_THROWS_AS((json().get<std::valarray<int>>()), json::type_error&);
 | 
			
		||||
 | 
			
		||||
                // does type really must be an array? or it rather must not be null?
 | 
			
		||||
                // that's what I thought when other test like this one broke
 | 
			
		||||
| 
						 | 
				
			
			@ -1057,6 +1068,7 @@ TEST_CASE("value conversion")
 | 
			
		|||
                CHECK_THROWS_WITH((json().get<std::vector<int>>()), "[json.exception.type_error.302] type must be array, but is null");
 | 
			
		||||
                CHECK_THROWS_WITH((json().get<std::vector<json>>()), "[json.exception.type_error.302] type must be array, but is null");
 | 
			
		||||
                CHECK_THROWS_WITH((json().get<std::list<json>>()), "[json.exception.type_error.302] type must be array, but is null");
 | 
			
		||||
                CHECK_THROWS_WITH((json().get<std::valarray<int>>()), "[json.exception.type_error.302] type must be array, but is null");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1204,4 +1204,33 @@ TEST_CASE("regression tests")
 | 
			
		|||
        std::string i = "\xef\xbb\xbf{\n   \"foo\": true\n}";
 | 
			
		||||
        CHECK_NOTHROW(json::parse(i.begin(), i.end()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("issue #702 - conversion from valarray<double> to json fails to build")
 | 
			
		||||
    {
 | 
			
		||||
        SECTION("original example")
 | 
			
		||||
        {
 | 
			
		||||
        std::valarray<double> v;
 | 
			
		||||
        nlohmann::json j;
 | 
			
		||||
        j["test"] = v;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("full example")
 | 
			
		||||
        {
 | 
			
		||||
            std::valarray<double> v = {1.2, 2.3, 3.4, 4.5};
 | 
			
		||||
            json j = v;
 | 
			
		||||
            std::valarray<double> vj = j;
 | 
			
		||||
 | 
			
		||||
            CHECK(j == json(vj));
 | 
			
		||||
            CHECK(v.size() == vj.size());
 | 
			
		||||
            for (size_t i = 0; i < v.size(); ++i)
 | 
			
		||||
            {
 | 
			
		||||
                CHECK(v[i] == vj[i]);
 | 
			
		||||
                CHECK(v[i] == j[i]);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            CHECK_THROWS_AS(json().get<std::valarray<double>>(), json::type_error&);
 | 
			
		||||
            CHECK_THROWS_WITH(json().get<std::valarray<double>>(),
 | 
			
		||||
                "[json.exception.type_error.302] type must be array, but is null");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue