Skip to content

object field accessors #103

Closed
Closed
@ropuls

Description

Hi Niels,

not sure if this is needed inside the class, however that pattern is widely in use here, and might be of use for other users as well.

template <typename T>
T get(json &value, const std::string &key, T defval = T()) {
    if (value.is_object()) {
        auto it = value.find(key);
        if (it != value.end()) {
            try {
                return it.value().get<T>();
            } catch (...) {

            }
        }
    }
    return defval;
}

void dispatch(const json &j) {
    std::string op = get<std::string>(j, "op");
    if (op == "replace") {
        ...
    } else if (op == "insert") {
        ...
    } else if (op == "select") {
        ...
    }
}

In a real implementation, names would need to be changed, and SFINAE type-checking shall be made if T is generally convertible from json's underlying types. It would also be good to avoid the internal exception, if possible, and have a non-throwing path (for me an exception is almost ever an error condition, whilst that new accessors gently asks "may I have it as T if that key is here"?

Another variant for c++14 and beyond users would be:

template <typename T>
std::optional<T> get(const json &j, const std::string &key) {
    ...
}

if (get(j, "op").value_or("")) { ... }

Which would make things even better/more precise.

Cheers,
Roman

PS: with gcc5 (stolen from their homepage) we can detect std::optional like this:

#ifdef __has_include
#  if __has_include(<optional>)
#    include <optional>
#    define have_optional 1
#  elif __has_include(<experimental/optional>)
#    include <experimental/optional>
#    define have_optional 1
#    define experimental_optional
#  else
#    define have_optional 0
#  endif
#endif

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions