Replies: 2 comments 3 replies
-
There are no functions with these signatures. Do you mean
There are more options. See https://json.nlohmann.me/features/element_access/ for a complete list.
You'd have to check if the key exists yourself (using Examples: auto j = json{{"foo", 42}};
// option 1
if(auto [_, inserted] = j.emplace("foo", 0); !inserted)
throw "key exists";
// option 2
if(j.contains("foo"))
throw "key exists";
j["foo"] = 0; Note that |
Beta Was this translation helpful? Give feedback.
-
I added these functions to do what I need: /// @brief Adds the key and value to the object. Throws, if the key already exists.
template<typename KeyType, typename ValueType>
void add(const KeyType& key, const ValueType& value)
{
if (contains(key))
{
JSON_THROW(out_of_range::create(499, detail::concat("Tried to add already existing key ", key), this));
}
(*this)[key] = value;
}
/// @brief Gets the value at that index from the array and puts it into v. Throws, if the index is out of range.
template<typename ValueType>
void get_to(size_type index, ValueType& v) const
{
if (!is_array())
{
JSON_THROW(type_error::create(305, detail::concat("cannot use get_to with a numeric argument with ", type_name()), this));
}
if (index >= m_value.array->size())
{
JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(index), " is out of range"), this));
}
(*this)[index].get_to(v);
}
/// @brief Gets the value at that index from the array. Throws, if the index is out of range.
template<typename ValueType>
constexpr auto get(size_type index) const
{
if (!is_array())
{
JSON_THROW(type_error::create(305, detail::concat("cannot use get with a numeric argument with ", type_name()), this));
}
if (index >= m_value.array->size())
{
JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(index), " is out of range"), this));
}
return (*this)[index].template get<ValueType>();
}
/// @brief Gets the value associated with that key from the object and puts it into v. Throws, if the key does not exists.
template<typename ValueType>
void get_to(typename object_t::key_type key, ValueType& v) const
{
if (!is_object())
{
JSON_THROW(type_error::create(305, detail::concat("cannot use get with a string argument with ", type_name()), this));
}
if (!contains(key))
{
JSON_THROW(out_of_range::create(498, detail::concat("Tried to get_to non-existing key ", key), this));
}
(*this)[key].get_to(v);
}
/// @brief Gets the value associated with that key from the object. Throws, if the key does not exists.
template<typename ValueType>
constexpr auto get(typename object_t::key_type key) const
{
if (!is_object())
{
JSON_THROW(type_error::create(305, detail::concat("cannot use get with a string argument with ", type_name()), this));
}
if (!contains(key))
{
JSON_THROW(out_of_range::create(497, detail::concat("Tried to get non-existing key ", key), this));
}
return (*this)[key].template get<ValueType>();
} (I didn't bother with |
Beta Was this translation helpful? Give feedback.
-
When getting values out of an object, I have these options:
object.get_to("Key", target);
(ortarget = object.get<decltype(target)>("Key");
). This throws an exception if the key is not present. Very much what I want.value = object["Key"];
object
is "modifiable", this will create the key if it is not present. Not what I want.object
is not "modifiable", this is undefined behavior. Super duper not what I want.When putting values into the object, I have these options:
object["Key"] = value;
object
is "modifiable", this will create the key and then overwrite it. Mostly what I want, but I'd prefer if it threw when the key already exists.object
is not "modifiable", the compilation fails with "method is not marked const". This is what I want.When I first started using the library, I used the
operator []
for both cases because it looks very clean. I learned the hard way that this operator does not what I want when getting values (Related: issues #289 and #2111), so I decided to useget_to
for getting values instead. But I can't find an equivalentset
orset_from
oradd
oradd_from
for setting values. (set
would overwrite an existing value andadd
would throw an exception.)This leaves an inconsistency in my code where I use one thing for getting values and a completely different thing for setting values.
Also, modern IDEs are awesome, so there is no reliable way of making sure that I don't still call the
operator []
to get a value somewhere. And the operator itself can't (reliably) distinguish between getting and setting, so I can't just put an assert there. I would like to outright remove theoperator []
s from json.hpp, to make sure that I can't accidentally use it, but I don't have an alternative for setting values. I woud add such a function myself (even if it's just for my cloned copy of the repo), but I don't know the internal details of how your code works, so I would very likely introduce a bug. Even just having a version that does almost what I want (e.g. overwrite if already exists) would make it a lot easier to modify it (e.g. throw if already exists).So to summarize: If there were dedicated functions to set values, just like there are dedicated functions to get values, this would
operator []
, slow but safe non-operator functions" ideaThat last point is quite important for me. If you disagree on how those functions should behave, I would still appreciate having anything at all over no options whatsoever. And if you don't want to change your public-facing API in this way, I would still very much appreciate if you could write an exemplary function and post that here, even though that won't make it into your repository.
Beta Was this translation helpful? Give feedback.
All reactions