| Home | Libraries | People | FAQ | More

### Non-throwing conversions

For the case where throwing exceptions is undesirable, Boost.JSON also provides a non-throwing version of `value_to`, the function template `try_value_to`. It returns `result`, a specialised variant that either holds a value or an `error_code`.

| Note
There's no non-throwing equivalent for `value_from`. This is simply because we haven't yet encountered a situation where `value_from` needed to communicate an error to the caller.

The library provides non-throwing conversions for all the categories of types it supports with `value_to`. If a user wants to use it with custom types, an overload of `tag_invoke` of this form needs to be provided:

    result_for<T, value>::type
    tag_invoke( const try_value_to_tag< T >&, const value& );

For the class `ip_address` from the section Custom conversions this overload may look like this:

    result_for< ip_address, value >::type
    tag_invoke( const try_value_to_tag< ip_address >&, value const& jv )
    {
        if( !jv.is_array() )
            return make_error_code( std::errc::invalid_argument );

        array const& arr = jv.get_array();
        if( arr.size() != 4 )
            return make_error_code( std::errc::invalid_argument );

        result< unsigned char > oct1 = try_value_to< unsigned char >( arr[0] );
        if( !oct1 )
            return make_error_code( std::errc::invalid_argument );

        result< unsigned char > oct2 = try_value_to< unsigned char >( arr[1] );
        if( !oct2 )
            return make_error_code( std::errc::invalid_argument );

        result< unsigned char > oct3 = try_value_to< unsigned char >( arr[2] );
        if( !oct3 )
            return make_error_code( std::errc::invalid_argument );

        result< unsigned char > oct4 = try_value_to< unsigned char >( arr[3] );
        if( !oct4 )
            return make_error_code( std::errc::invalid_argument );

        return ip_address{ *oct1, *oct2, *oct3, *oct4 };
    }

The overload lets us use `ip_address` with `try_value_to`.

    value jv = parse( R"([127,0,0,12])" );

    result< ip_address > addr = try_value_to< ip_address >( jv );
    assert( addr.has_value() );

    ip_address addr2{ 127, 0, 0, 12 };
    assert(std::equal(
        addr->begin(), addr->end(), addr2.begin() ));

    // this fails without exception
    addr = try_value_to< ip_address >( value() );
    assert( addr.has_error() );

If `try_value_to` is used with a type, for which there's no `tag_invoke` overload of the form described in this section, but there is one of the form intended for `value_to`, then the library still tries to perform the conversion. It uses the throwing overload, and attempts to convert any thrown exception into an `error_code`. Note, though, that such approach will likely be slower then a dedicated overload.

The opposite is also true: if there's a `tag_invoke` overload intended for `try_value_to`, but not for `value_to`, then calling ``value_to`` will invoke the non-throwing overload, then construct a `system_error` from the `error_code` and throw it. Due to these fallbacks, it is recommended that users provide the overload from this section, rather then the other one, if they ever intend to use `try_value_to`.