make sure values are overwritten in from_json overloads
Caused unexpected behaviors when using get_to with values previously set. Fixes !1511
This commit is contained in:
		
							parent
							
								
									b21c04c938
								
							
						
					
					
						commit
						2806b201a8
					
				
					 4 changed files with 206 additions and 41 deletions
				
			
		| 
						 | 
				
			
			@ -136,6 +136,7 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
 | 
			
		|||
    {
 | 
			
		||||
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
 | 
			
		||||
    }
 | 
			
		||||
    l.clear();
 | 
			
		||||
    std::transform(j.rbegin(), j.rend(),
 | 
			
		||||
                   std::front_inserter(l), [](const BasicJsonType & i)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -182,14 +183,16 @@ auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, p
 | 
			
		|||
{
 | 
			
		||||
    using std::end;
 | 
			
		||||
 | 
			
		||||
    arr.reserve(j.size());
 | 
			
		||||
    ConstructibleArrayType ret;
 | 
			
		||||
    ret.reserve(j.size());
 | 
			
		||||
    std::transform(j.begin(), j.end(),
 | 
			
		||||
                   std::inserter(arr, end(arr)), [](const BasicJsonType & i)
 | 
			
		||||
                   std::inserter(ret, end(ret)), [](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 ConstructibleArrayType::value_type>();
 | 
			
		||||
    });
 | 
			
		||||
    arr = std::move(ret);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename BasicJsonType, typename ConstructibleArrayType>
 | 
			
		||||
| 
						 | 
				
			
			@ -198,14 +201,16 @@ void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
 | 
			
		|||
{
 | 
			
		||||
    using std::end;
 | 
			
		||||
 | 
			
		||||
    ConstructibleArrayType ret;
 | 
			
		||||
    std::transform(
 | 
			
		||||
        j.begin(), j.end(), std::inserter(arr, end(arr)),
 | 
			
		||||
        j.begin(), j.end(), std::inserter(ret, end(ret)),
 | 
			
		||||
        [](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 ConstructibleArrayType::value_type>();
 | 
			
		||||
    });
 | 
			
		||||
    arr = std::move(ret);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename BasicJsonType, typename ConstructibleArrayType,
 | 
			
		||||
| 
						 | 
				
			
			@ -239,15 +244,17 @@ void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
 | 
			
		|||
        JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ConstructibleObjectType ret;
 | 
			
		||||
    auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
 | 
			
		||||
    using value_type = typename ConstructibleObjectType::value_type;
 | 
			
		||||
    std::transform(
 | 
			
		||||
        inner_object->begin(), inner_object->end(),
 | 
			
		||||
        std::inserter(obj, obj.begin()),
 | 
			
		||||
        std::inserter(ret, ret.begin()),
 | 
			
		||||
        [](typename BasicJsonType::object_t::value_type const & p)
 | 
			
		||||
    {
 | 
			
		||||
        return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
 | 
			
		||||
    });
 | 
			
		||||
    obj = std::move(ret);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// overload for arithmetic types, not chosen for basic_json template arguments
 | 
			
		||||
| 
						 | 
				
			
			@ -319,6 +326,7 @@ void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>&
 | 
			
		|||
    {
 | 
			
		||||
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
 | 
			
		||||
    }
 | 
			
		||||
    m.clear();
 | 
			
		||||
    for (const auto& p : j)
 | 
			
		||||
    {
 | 
			
		||||
        if (JSON_UNLIKELY(not p.is_array()))
 | 
			
		||||
| 
						 | 
				
			
			@ -338,6 +346,7 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE
 | 
			
		|||
    {
 | 
			
		||||
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
 | 
			
		||||
    }
 | 
			
		||||
    m.clear();
 | 
			
		||||
    for (const auto& p : j)
 | 
			
		||||
    {
 | 
			
		||||
        if (JSON_UNLIKELY(not p.is_array()))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -192,10 +192,19 @@ struct is_constructible_object_type_impl <
 | 
			
		|||
    using object_t = typename BasicJsonType::object_t;
 | 
			
		||||
 | 
			
		||||
    static constexpr bool value =
 | 
			
		||||
        (std::is_constructible<typename ConstructibleObjectType::key_type, typename object_t::key_type>::value and
 | 
			
		||||
         std::is_same<typename object_t::mapped_type, typename ConstructibleObjectType::mapped_type>::value) or
 | 
			
		||||
        (has_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type>::value or
 | 
			
		||||
         has_non_default_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type >::value);
 | 
			
		||||
        (std::is_default_constructible<ConstructibleObjectType>::value and
 | 
			
		||||
         (std::is_move_assignable<ConstructibleObjectType>::value or
 | 
			
		||||
          std::is_copy_assignable<ConstructibleObjectType>::value) and
 | 
			
		||||
         (std::is_constructible<typename ConstructibleObjectType::key_type,
 | 
			
		||||
          typename object_t::key_type>::value and
 | 
			
		||||
          std::is_same <
 | 
			
		||||
          typename object_t::mapped_type,
 | 
			
		||||
          typename ConstructibleObjectType::mapped_type >::value)) or
 | 
			
		||||
        (has_from_json<BasicJsonType,
 | 
			
		||||
         typename ConstructibleObjectType::mapped_type>::value or
 | 
			
		||||
         has_non_default_from_json <
 | 
			
		||||
         BasicJsonType,
 | 
			
		||||
         typename ConstructibleObjectType::mapped_type >::value);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename BasicJsonType, typename ConstructibleObjectType>
 | 
			
		||||
| 
						 | 
				
			
			@ -278,20 +287,24 @@ struct is_constructible_array_type_impl <
 | 
			
		|||
    BasicJsonType, ConstructibleArrayType,
 | 
			
		||||
    enable_if_t<not std::is_same<ConstructibleArrayType,
 | 
			
		||||
    typename BasicJsonType::value_type>::value and
 | 
			
		||||
    is_detected<value_type_t, ConstructibleArrayType>::value and
 | 
			
		||||
    is_detected<iterator_t, ConstructibleArrayType>::value and
 | 
			
		||||
    is_complete_type<
 | 
			
		||||
    detected_t<value_type_t, ConstructibleArrayType>>::value >>
 | 
			
		||||
    std::is_default_constructible<ConstructibleArrayType>::value and
 | 
			
		||||
(std::is_move_assignable<ConstructibleArrayType>::value or
 | 
			
		||||
 std::is_copy_assignable<ConstructibleArrayType>::value) and
 | 
			
		||||
is_detected<value_type_t, ConstructibleArrayType>::value and
 | 
			
		||||
is_detected<iterator_t, ConstructibleArrayType>::value and
 | 
			
		||||
is_complete_type<
 | 
			
		||||
detected_t<value_type_t, ConstructibleArrayType>>::value >>
 | 
			
		||||
{
 | 
			
		||||
    static constexpr bool value =
 | 
			
		||||
        // This is needed because json_reverse_iterator has a ::iterator type,
 | 
			
		||||
        // furthermore, std::back_insert_iterator (and other iterators) have a base class `iterator`...
 | 
			
		||||
        // Therefore it is detected as a ConstructibleArrayType.
 | 
			
		||||
        // The real fix would be to have an Iterable concept.
 | 
			
		||||
        not is_iterator_traits <
 | 
			
		||||
        iterator_traits<ConstructibleArrayType >>::value and
 | 
			
		||||
        // furthermore, std::back_insert_iterator (and other iterators) have a
 | 
			
		||||
        // base class `iterator`... Therefore it is detected as a
 | 
			
		||||
        // ConstructibleArrayType. The real fix would be to have an Iterable
 | 
			
		||||
        // concept.
 | 
			
		||||
        not is_iterator_traits<iterator_traits<ConstructibleArrayType>>::value and
 | 
			
		||||
 | 
			
		||||
        (std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t::value_type>::value or
 | 
			
		||||
        (std::is_same<typename ConstructibleArrayType::value_type,
 | 
			
		||||
         typename BasicJsonType::array_t::value_type>::value or
 | 
			
		||||
         has_from_json<BasicJsonType,
 | 
			
		||||
         typename ConstructibleArrayType::value_type>::value or
 | 
			
		||||
         has_non_default_from_json <
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue