Add an error_handler parameter for UTF-8 to the binary readers and writers (#5746)

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-10-04 12:13:49 +02:00
committed by GitHub
parent f56b418c56
commit 73e9eae3c1
30 changed files with 1794 additions and 422 deletions
+81 -54
View File
@@ -195,9 +195,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// used by the vector-returning to_* overloads
template<typename CharType> using vector_binary_writer =
::nlohmann::detail::binary_writer<basic_json, CharType, ::nlohmann::detail::output_vector_sink<CharType>>;
template<typename CharType> static vector_binary_writer<CharType> vector_writer(std::vector<CharType>& v)
template<typename CharType> static vector_binary_writer<CharType> vector_writer(
std::vector<CharType>& v, const ::nlohmann::detail::error_handler_t error_handler = ::nlohmann::detail::binary_writer_default_error_handler())
{
return vector_binary_writer<CharType>(::nlohmann::detail::output_vector_sink<CharType>(v));
return vector_binary_writer<CharType>(::nlohmann::detail::output_vector_sink<CharType>(v), error_handler);
}
JSON_PRIVATE_UNLESS_TESTED:
@@ -5583,11 +5584,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template<typename InputAdapterType>
static basic_json from_binary_impl(InputAdapterType ia, const input_format_t format,
const bool strict, const bool allow_exceptions,
const error_handler_t error_handler = error_handler_t::keep,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{
basic_json result;
detail::json_sax_dom_parser<basic_json, InputAdapterType> sdp(result, allow_exceptions);
binary_reader<InputAdapterType> reader(std::move(ia), format);
binary_reader<InputAdapterType> reader(std::move(ia), format, error_handler);
if (!reader.sax_parse(&sdp, strict, tag_handler))
{
result = value_t::discarded;
@@ -5605,78 +5607,87 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
public:
/// @brief create a CBOR serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
static std::vector<std::uint8_t> to_cbor(const basic_json& j)
static std::vector<std::uint8_t> to_cbor(const basic_json& j,
const error_handler_t error_handler = detail::binary_writer_default_error_handler())
{
std::vector<std::uint8_t> result;
result.reserve(detail::binary_reserve_hint(j));
vector_writer(result).write_cbor(j);
vector_writer(result, error_handler).write_cbor(j);
return result;
}
/// @brief create a CBOR serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o,
const error_handler_t error_handler = detail::binary_writer_default_error_handler())
{
binary_writer<std::uint8_t>(o).write_cbor(j);
binary_writer<std::uint8_t>(o, error_handler).write_cbor(j);
}
/// @brief create a CBOR serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
static void to_cbor(const basic_json& j, detail::output_adapter<char> o,
const error_handler_t error_handler = detail::binary_writer_default_error_handler())
{
binary_writer<char>(o).write_cbor(j);
binary_writer<char>(o, error_handler).write_cbor(j);
}
/// @brief create a MessagePack serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
static std::vector<std::uint8_t> to_msgpack(const basic_json& j,
const error_handler_t error_handler = error_handler_t::keep)
{
std::vector<std::uint8_t> result;
result.reserve(detail::binary_reserve_hint(j));
vector_writer(result).write_msgpack(j);
vector_writer(result, error_handler).write_msgpack(j);
return result;
}
/// @brief create a MessagePack serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o,
const error_handler_t error_handler = error_handler_t::keep)
{
binary_writer<std::uint8_t>(o).write_msgpack(j);
binary_writer<std::uint8_t>(o, error_handler).write_msgpack(j);
}
/// @brief create a MessagePack serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
static void to_msgpack(const basic_json& j, detail::output_adapter<char> o,
const error_handler_t error_handler = error_handler_t::keep)
{
binary_writer<char>(o).write_msgpack(j);
binary_writer<char>(o, error_handler).write_msgpack(j);
}
/// @brief create a UBJSON serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
const bool use_size = false,
const bool use_type = false)
const bool use_type = false,
const error_handler_t error_handler = detail::binary_writer_default_error_handler())
{
std::vector<std::uint8_t> result;
result.reserve(detail::binary_reserve_hint(j));
vector_writer(result).write_ubjson(j, use_size, use_type);
vector_writer(result, error_handler).write_ubjson(j, use_size, use_type);
return result;
}
/// @brief create a UBJSON serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
const bool use_size = false, const bool use_type = false)
const bool use_size = false, const bool use_type = false,
const error_handler_t error_handler = detail::binary_writer_default_error_handler())
{
binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
binary_writer<std::uint8_t>(o, error_handler).write_ubjson(j, use_size, use_type);
}
/// @brief create a UBJSON serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
const bool use_size = false, const bool use_type = false)
const bool use_size = false, const bool use_type = false,
const error_handler_t error_handler = detail::binary_writer_default_error_handler())
{
binary_writer<char>(o).write_ubjson(j, use_size, use_type);
binary_writer<char>(o, error_handler).write_ubjson(j, use_size, use_type);
}
/// @brief create a BJData serialization of a given JSON value
@@ -5684,11 +5695,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
const bool use_size = false,
const bool use_type = false,
const bjdata_version_t version = bjdata_version_t::draft2)
const bjdata_version_t version = bjdata_version_t::draft2,
const error_handler_t error_handler = detail::binary_writer_default_error_handler())
{
std::vector<std::uint8_t> result;
result.reserve(detail::binary_reserve_hint(j));
vector_writer(result).write_ubjson(j, use_size, use_type, true, true, version);
vector_writer(result, error_handler).write_ubjson(j, use_size, use_type, true, true, version);
return result;
}
@@ -5696,42 +5708,47 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
const bool use_size = false, const bool use_type = false,
const bjdata_version_t version = bjdata_version_t::draft2)
const bjdata_version_t version = bjdata_version_t::draft2,
const error_handler_t error_handler = detail::binary_writer_default_error_handler())
{
binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
binary_writer<std::uint8_t>(o, error_handler).write_ubjson(j, use_size, use_type, true, true, version);
}
/// @brief create a BJData serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
const bool use_size = false, const bool use_type = false,
const bjdata_version_t version = bjdata_version_t::draft2)
const bjdata_version_t version = bjdata_version_t::draft2,
const error_handler_t error_handler = detail::binary_writer_default_error_handler())
{
binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
binary_writer<char>(o, error_handler).write_ubjson(j, use_size, use_type, true, true, version);
}
/// @brief create a BSON serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_bson/
static std::vector<std::uint8_t> to_bson(const basic_json& j)
static std::vector<std::uint8_t> to_bson(const basic_json& j,
const error_handler_t error_handler = detail::binary_writer_default_error_handler())
{
std::vector<std::uint8_t> result;
result.reserve(detail::binary_reserve_hint(j));
vector_writer(result).write_bson(j);
vector_writer(result, error_handler).write_bson(j);
return result;
}
/// @brief create a BSON serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_bson/
static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
const error_handler_t error_handler = detail::binary_writer_default_error_handler())
{
binary_writer<std::uint8_t>(o).write_bson(j);
binary_writer<std::uint8_t>(o, error_handler).write_bson(j);
}
/// @brief create a BSON serialization of a given JSON value
/// @sa https://json.nlohmann.me/api/basic_json/to_bson/
static void to_bson(const basic_json& j, detail::output_adapter<char> o)
static void to_bson(const basic_json& j, detail::output_adapter<char> o,
const error_handler_t error_handler = detail::binary_writer_default_error_handler())
{
binary_writer<char>(o).write_bson(j);
binary_writer<char>(o, error_handler).write_bson(j);
}
/// @brief create a BON8 serialization of a given JSON value
@@ -5765,9 +5782,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
static basic_json from_cbor(InputType&& i,
const bool strict = true,
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error,
const error_handler_t error_handler = error_handler_t::keep)
{
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::cbor, strict, allow_exceptions, tag_handler);
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::cbor, strict, allow_exceptions, error_handler, tag_handler);
}
/// @brief create a JSON value from an input in CBOR format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -5778,9 +5796,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
static basic_json from_cbor(IteratorType first, SentinelType last,
const bool strict = true,
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error,
const error_handler_t error_handler = error_handler_t::keep)
{
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::cbor, strict, allow_exceptions, tag_handler);
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::cbor, strict, allow_exceptions, error_handler, tag_handler);
}
template<typename T>
@@ -5801,7 +5820,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{
return from_binary_impl(i.get(), input_format_t::cbor, strict, allow_exceptions, tag_handler);
return from_binary_impl(i.get(), input_format_t::cbor, strict, allow_exceptions, error_handler_t::keep, tag_handler);
}
/// @brief create a JSON value from an input in MessagePack format
@@ -5810,9 +5829,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json from_msgpack(InputType&& i,
const bool strict = true,
const bool allow_exceptions = true)
const bool allow_exceptions = true,
const error_handler_t error_handler = error_handler_t::keep)
{
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::msgpack, strict, allow_exceptions);
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::msgpack, strict, allow_exceptions, error_handler);
}
/// @brief create a JSON value from an input in MessagePack format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -5822,9 +5842,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json from_msgpack(IteratorType first, SentinelType last,
const bool strict = true,
const bool allow_exceptions = true)
const bool allow_exceptions = true,
const error_handler_t error_handler = error_handler_t::keep)
{
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::msgpack, strict, allow_exceptions);
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::msgpack, strict, allow_exceptions, error_handler);
}
template<typename T>
@@ -5852,9 +5873,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json from_ubjson(InputType&& i,
const bool strict = true,
const bool allow_exceptions = true)
const bool allow_exceptions = true,
const error_handler_t error_handler = error_handler_t::keep)
{
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::ubjson, strict, allow_exceptions);
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::ubjson, strict, allow_exceptions, error_handler);
}
/// @brief create a JSON value from an input in UBJSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -5864,9 +5886,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json from_ubjson(IteratorType first, SentinelType last,
const bool strict = true,
const bool allow_exceptions = true)
const bool allow_exceptions = true,
const error_handler_t error_handler = error_handler_t::keep)
{
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::ubjson, strict, allow_exceptions);
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::ubjson, strict, allow_exceptions, error_handler);
}
template<typename T>
@@ -5894,9 +5917,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json from_bjdata(InputType&& i,
const bool strict = true,
const bool allow_exceptions = true)
const bool allow_exceptions = true,
const error_handler_t error_handler = error_handler_t::keep)
{
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::bjdata, strict, allow_exceptions);
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::bjdata, strict, allow_exceptions, error_handler);
}
/// @brief create a JSON value from an input in BJData format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -5906,9 +5930,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json from_bjdata(IteratorType first, SentinelType last,
const bool strict = true,
const bool allow_exceptions = true)
const bool allow_exceptions = true,
const error_handler_t error_handler = error_handler_t::keep)
{
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bjdata, strict, allow_exceptions);
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bjdata, strict, allow_exceptions, error_handler);
}
/// @brief create a JSON value from an input in BON8 format
@@ -5940,9 +5965,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json from_bson(InputType&& i,
const bool strict = true,
const bool allow_exceptions = true)
const bool allow_exceptions = true,
const error_handler_t error_handler = error_handler_t::keep)
{
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::bson, strict, allow_exceptions);
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::bson, strict, allow_exceptions, error_handler);
}
/// @brief create a JSON value from an input in BSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -5952,9 +5978,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json from_bson(IteratorType first, SentinelType last,
const bool strict = true,
const bool allow_exceptions = true)
const bool allow_exceptions = true,
const error_handler_t error_handler = error_handler_t::keep)
{
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bson, strict, allow_exceptions);
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bson, strict, allow_exceptions, error_handler);
}
template<typename T>