mirror of
https://github.com/boostorg/exception.git
synced 2026-07-21 13:13:43 +00:00
Improved SFINAE in the JSON encoders
This commit is contained in:
+16
-11
@@ -1084,8 +1084,9 @@ struct boost_json_encoder
|
|||||||
{
|
{
|
||||||
boost::json::value & v_;
|
boost::json::value & v_;
|
||||||
|
|
||||||
// Enabled if x is assignable to boost::json::value, or
|
// Uses unspecified SFINAE expression designed to make the
|
||||||
// if tag_invoke is defined for boost::json::value_from_tag.
|
// overload selected only if no other compatible overload is found.
|
||||||
|
// Implemented in terms of boost::json::value_from.
|
||||||
template <class T>
|
template <class T>
|
||||||
friend void output( boost_json_encoder &, T const & x );
|
friend void output( boost_json_encoder &, T const & x );
|
||||||
|
|
||||||
@@ -1114,7 +1115,9 @@ struct nlohmann_json_encoder
|
|||||||
{
|
{
|
||||||
Json & j_;
|
Json & j_;
|
||||||
|
|
||||||
// Enabled if to_json is available for Json and T.
|
// Uses unspecified SFINAE expression designed to make the
|
||||||
|
// overload selected only if no other compatible overload is found.
|
||||||
|
// Implemented in terms of to_json.
|
||||||
template <class T>
|
template <class T>
|
||||||
friend void output( nlohmann_json_encoder &, T const & x );
|
friend void output( nlohmann_json_encoder &, T const & x );
|
||||||
|
|
||||||
@@ -1156,8 +1159,9 @@ struct boost_json_encoder
|
|||||||
{
|
{
|
||||||
boost::json::value & v_;
|
boost::json::value & v_;
|
||||||
|
|
||||||
// Enabled if x is assignable to boost::json::value, or
|
// Uses unspecified SFINAE expression designed to make the
|
||||||
// if tag_invoke is defined for boost::json::value_from_tag.
|
// overload selected only if no other compatible overload is found.
|
||||||
|
// Implemented in terms of boost::json::value_from.
|
||||||
template <class T>
|
template <class T>
|
||||||
friend void output( boost_json_encoder &, T const & x );
|
friend void output( boost_json_encoder &, T const & x );
|
||||||
|
|
||||||
@@ -1168,10 +1172,7 @@ struct boost_json_encoder
|
|||||||
} }
|
} }
|
||||||
----
|
----
|
||||||
|
|
||||||
The `boost_json_encoder` type serializes objects to JSON format using https://www.boost.org/doc/libs/release/libs/json/[Boost.JSON]. The `output` function is enabled for:
|
The `boost_json_encoder` type serializes objects to JSON format using https://www.boost.org/doc/libs/release/libs/json/[Boost.JSON]. The `output` function is implemented in terms of `boost::json::value_from`.
|
||||||
|
|
||||||
* Types directly assignable to `boost::json::value`
|
|
||||||
* Types for which a `tag_invoke` overload for `value_from_tag` can be found via ADL
|
|
||||||
|
|
||||||
See <<tutorial_serialization>>.
|
See <<tutorial_serialization>>.
|
||||||
|
|
||||||
@@ -1592,7 +1593,9 @@ struct nlohmann_json_encoder
|
|||||||
{
|
{
|
||||||
Json & j_;
|
Json & j_;
|
||||||
|
|
||||||
// Enabled if to_json is available for Json and T.
|
// Uses unspecified SFINAE expression designed to make the
|
||||||
|
// overload selected only if no other compatible overload is found.
|
||||||
|
// Implemented in terms of to_json.
|
||||||
template <class T>
|
template <class T>
|
||||||
friend void output( nlohmann_json_encoder &, T const & x );
|
friend void output( nlohmann_json_encoder &, T const & x );
|
||||||
|
|
||||||
@@ -1603,7 +1606,9 @@ struct nlohmann_json_encoder
|
|||||||
} }
|
} }
|
||||||
----
|
----
|
||||||
|
|
||||||
The `nlohmann_json_encoder` type serializes objects to JSON format based on ADL calls to `to_json`. This is compatible with https://github.com/nlohmann/json[nlohmann/json]. See <<tutorial_serialization>>.
|
The `nlohmann_json_encoder` type serializes objects to JSON format based on ADL calls to `to_json`. This is compatible with https://github.com/nlohmann/json[nlohmann/json].
|
||||||
|
|
||||||
|
See <<tutorial_serialization>>.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|||||||
@@ -6,43 +6,36 @@
|
|||||||
#ifndef BOOST_EXCEPTION_SERIALIZATION_BOOST_JSON_ENCODER_HPP_INCLUDED
|
#ifndef BOOST_EXCEPTION_SERIALIZATION_BOOST_JSON_ENCODER_HPP_INCLUDED
|
||||||
#define BOOST_EXCEPTION_SERIALIZATION_BOOST_JSON_ENCODER_HPP_INCLUDED
|
#define BOOST_EXCEPTION_SERIALIZATION_BOOST_JSON_ENCODER_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
namespace boost { namespace json {
|
||||||
|
|
||||||
|
class value;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void value_from(T &&, value &);
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
boost
|
boost
|
||||||
{
|
{
|
||||||
namespace
|
|
||||||
json
|
|
||||||
{
|
|
||||||
class value;
|
|
||||||
struct value_from_tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
exception_serialization
|
exception_serialization
|
||||||
{
|
{
|
||||||
// Baast.JSON does not provide ADL interface for serializing user-defined types.
|
template <class Value = boost::json::value>
|
||||||
// This limits the functionality of boost_json_encoder to only types that provide tag_invoke.
|
|
||||||
template <class Value = boost::json::value, class ValueFromTag = boost::json::value_from_tag>
|
|
||||||
struct
|
struct
|
||||||
boost_json_encoder_
|
boost_json_encoder_
|
||||||
{
|
{
|
||||||
Value & v_;
|
Value & v_;
|
||||||
|
|
||||||
template <class T>
|
template <class Encoder, class T, class... Deprioritize>
|
||||||
friend
|
friend
|
||||||
auto
|
typename std::enable_if<std::is_same<Encoder, boost_json_encoder_>::value>::type
|
||||||
output(boost_json_encoder_ & e, T const & x) -> decltype(std::declval<Value &>() = x, void())
|
output(Encoder & e, T const & x, Deprioritize...)
|
||||||
{
|
{
|
||||||
e.v_ = x;
|
boost::json::value_from(x, e.v_);
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
friend
|
|
||||||
auto
|
|
||||||
output(boost_json_encoder_ & e, T const & x) -> decltype(tag_invoke(std::declval<ValueFromTag>(), std::declval<Value &>(), x), void())
|
|
||||||
{
|
|
||||||
tag_invoke(ValueFromTag{}, e.v_, x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#ifndef BOOST_EXCEPTION_SERIALIZATION_NLOHMANN_JSON_ENCODER_HPP_INCLUDED
|
#ifndef BOOST_EXCEPTION_SERIALIZATION_NLOHMANN_JSON_ENCODER_HPP_INCLUDED
|
||||||
#define BOOST_EXCEPTION_SERIALIZATION_NLOHMANN_JSON_ENCODER_HPP_INCLUDED
|
#define BOOST_EXCEPTION_SERIALIZATION_NLOHMANN_JSON_ENCODER_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@@ -20,12 +21,12 @@ boost
|
|||||||
{
|
{
|
||||||
Json & j_;
|
Json & j_;
|
||||||
|
|
||||||
template <class T>
|
template <class Encoder, class T, class... Deprioritize>
|
||||||
friend
|
friend typename std::enable_if<std::is_same<Encoder, nlohmann_json_encoder>::value, Json *>::type
|
||||||
auto
|
output(Encoder & e, T const & x, Deprioritize...)
|
||||||
output(nlohmann_json_encoder & e, T const & x) -> decltype(to_json(std::declval<Json &>(), x))
|
|
||||||
{
|
{
|
||||||
to_json(e.j_, x);
|
to_json(e.j_, x);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using output_encoder = boost::exception_serialization::boost_json_encoder;
|
using output_encoder = boost::exception_serialization::boost_json_encoder;
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@ boost
|
|||||||
|
|
||||||
typedef boost::error_info<struct my_error1_, int> my_error1;
|
typedef boost::error_info<struct my_error1_, int> my_error1;
|
||||||
typedef boost::error_info<struct my_error2_, std::string> my_error2;
|
typedef boost::error_info<struct my_error2_, std::string> my_error2;
|
||||||
|
typedef boost::error_info<struct my_error4_, std::vector<int>> my_error4;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
my_info
|
my_info
|
||||||
@@ -97,6 +99,13 @@ check_output(boost::json::value const & j, bool has_source_location)
|
|||||||
auto const & mij = obj.at("my_error3_").as_object();
|
auto const & mij = obj.at("my_error3_").as_object();
|
||||||
BOOST_TEST_EQ(mij.at("code").as_int64(), 1);
|
BOOST_TEST_EQ(mij.at("code").as_int64(), 1);
|
||||||
BOOST_TEST_EQ(mij.at("message").as_string(), "error one");
|
BOOST_TEST_EQ(mij.at("message").as_string(), "error one");
|
||||||
|
|
||||||
|
BOOST_TEST(obj.contains("my_error4_"));
|
||||||
|
auto const & vec = obj.at("my_error4_").as_array();
|
||||||
|
BOOST_TEST_EQ(vec.size(), 3u);
|
||||||
|
BOOST_TEST_EQ(vec[0].as_int64(), 1);
|
||||||
|
BOOST_TEST_EQ(vec[1].as_int64(), 2);
|
||||||
|
BOOST_TEST_EQ(vec[2].as_int64(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -111,7 +120,8 @@ main()
|
|||||||
e <<
|
e <<
|
||||||
my_error1(42) <<
|
my_error1(42) <<
|
||||||
my_error2("hello") <<
|
my_error2("hello") <<
|
||||||
my_error3({1, "error one"});
|
my_error3({1, "error one"}) <<
|
||||||
|
my_error4({1, 2, 3});
|
||||||
BOOST_THROW_EXCEPTION(e);
|
BOOST_THROW_EXCEPTION(e);
|
||||||
}
|
}
|
||||||
catch( test_exception & e )
|
catch( test_exception & e )
|
||||||
@@ -132,7 +142,8 @@ main()
|
|||||||
e <<
|
e <<
|
||||||
my_error1(42) <<
|
my_error1(42) <<
|
||||||
my_error2("hello") <<
|
my_error2("hello") <<
|
||||||
my_error3({1, "error one"});
|
my_error3({1, "error one"}) <<
|
||||||
|
my_error4({1, 2, 3});
|
||||||
BOOST_THROW_EXCEPTION(e);
|
BOOST_THROW_EXCEPTION(e);
|
||||||
}
|
}
|
||||||
catch( ... )
|
catch( ... )
|
||||||
|
|||||||
Reference in New Issue
Block a user