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

Better diagnostic for value_to errors on described structures #1069

Open
sdebionne opened this issue Feb 6, 2025 · 2 comments
Open

Better diagnostic for value_to errors on described structures #1069

sdebionne opened this issue Feb 6, 2025 · 2 comments

Comments

@sdebionne
Copy link

Given the following use case that comes from the documentation:

#include <iostream>
#include <string>

#include <boost/json/src.hpp>
#include <boost/describe.hpp>
#include <boost/exception/diagnostic_information.hpp>

struct money
{
    std::string currency;
    double value;
};

BOOST_DESCRIBE_STRUCT(money, (), (currency, value))

struct test
{
    double pi;
    bool happy;
    money object;
};

BOOST_DESCRIBE_STRUCT(test, (), (pi, happy, object))

int main()
{
    boost::json::value jv = {
        { "pi", 3.141 },
        { "happy", true },
        {"object", {
            //{ "currency", "USD" },
            { "value", 42.99 }
        }}
        };

    try {
        test res = boost::json::value_to<test>(jv);
    }
    catch (std::exception const& ex) {
        std::cerr << boost::diagnostic_information(ex, true) << std::endl;
    }

    return 0;
}

The missing currency member gives the following exception:

Dynamic exception type: boost::detail::with_throw_location<boost::system::system_error>
std::exception::what: unknown name [boost.json:39 at /nobackup/lid00lima21/debionne/miniconda3/envs/lima2/include/boost/json/detail/value_to.hpp:371 in function 'operator()']

It would be interesting to have an information where the exception occurred in the json value during value_to conversion. Ideally something like errinfo_json_path="object.concurreny".

@kiwixz
Copy link

kiwixz commented Feb 8, 2025

I also miss that feature very much but I don't know if that's possible with only the error code, so I worry this will get wontfix-ed...

FYI I implemented it with exceptions in my boost::pfr tag_invoke (which I use instead of describing structs):

template <typename T, typename Context>
requires IsJsonAggregate<T>::value
T tag_invoke(boost::json::value_to_tag<T>, const boost::json::value& json, const Context& ctx) {
    const boost::json::object& obj = json.as_object();

    T r;

    boost::pfr::for_each_field(r, [&](auto& field, auto i) {
        std::string_view name = boost::pfr::get_name<i, T>();

        auto it = obj.find(name);
        if (it == obj.end())
            throw Exception{"Missing field {}", name};

        try {
            field = boost::json::value_to<std::decay_t<decltype(field)>>(it->value(), ctx);
        }
        catch (const std::exception& ex) {
            throw Exception{"Could not parse {}: {}", name, ex.what()};
        }
    });

    return r;
}

@grisumbras
Copy link
Member

A contributor is working on something in this area, and I also have some ideas. But most likely such feature will require customisation, potentially defining a macro.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants