Compare commits

..
Author SHA1 Message Date
Niels Lohmann bdaa8381d7 Update the supported compiler list and the CITATION.cff repository link
The README's compiler list still named GCC 14.2, Clang 21.0, Apple
Clang 16.0, Intel C++ 17.0.2, nvcc 11.0.221, and MSVC up to 2022,
which no longer matches the CI matrix. List what the workflows test
now, with versions taken from the compiler identification in the CI
logs of the latest develop runs: GCC 4.8 - 16.2, Clang 3.4 - 22.1,
Apple Clang 15.0 - 21.0 (Xcode 15.0.1 up to macos-latest), icpc
2021.10, icpx 2025.3, nvcc 11.8 - 12.6, nvc++ 25.5, and MSVC 2015 -
2026. Apple Clang now starts at 15.0 because CI no longer runs older
Xcode versions; icpc 2021.10 is the last release of that compiler.

CITATION.cff pointed repository-code at the user profile instead of
the repository.

Documentation and metadata only; the library is unchanged.

Part of #5716

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-30 09:44:53 +02:00
Niels Lohmann 85fec73da7 Make the json.tar.xz release archive configure standalone
The json.tar.xz rule packed neither src/modules nor tests, but the
top-level CMakeLists.txt needs src/modules for
NLOHMANN_JSON_BUILD_MODULES=ON and defaulted JSON_BuildTests to ON for
a main project. A standalone configure of the extracted archive failed
at add_subdirectory(tests), and enabling the module failed at
add_subdirectory(src/modules).

Add src/modules to the archive, and default JSON_BuildTests to ON only
if tests/CMakeLists.txt exists, so a repository checkout still builds
the tests by default while the archive configures out of the box. Use
GNU tar via a TAR variable (gtar if present, else tar), the same way
SED is found, instead of hard-coding gtar. The library, its public API,
and its ABI are unchanged.

Part of #5716

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-30 09:40:26 +02:00
18 changed files with 529 additions and 166 deletions
+1
View File
@@ -51,6 +51,7 @@ cc_library(
"include/nlohmann/detail/meta/detected.hpp",
"include/nlohmann/detail/meta/identity_tag.hpp",
"include/nlohmann/detail/meta/is_sax.hpp",
"include/nlohmann/detail/meta/logic.hpp",
"include/nlohmann/detail/meta/std_fs.hpp",
"include/nlohmann/detail/meta/type_traits.hpp",
"include/nlohmann/detail/meta/void_t.hpp",
+1 -1
View File
@@ -10,5 +10,5 @@ title: "JSON for Modern C++"
version: 3.12.0
date-released: 2025-04-07
license: MIT
repository-code: "https://github.com/nlohmann"
repository-code: "https://github.com/nlohmann/json"
url: https://json.nlohmann.me
+4 -1
View File
@@ -42,8 +42,11 @@ endif()
## OPTIONS
##
# Build the tests by default only for the main project and only if the tests
# directory exists (the release archive json.tar.xz does not contain it).
# VERSION_GREATER_EQUAL is not available in older CMake (< 3.7)
if(${MAIN_PROJECT} AND (${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13))
if(${MAIN_PROJECT} AND (${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13)
AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt")
set(JSON_BuildTests_INIT ON)
else()
set(JSON_BuildTests_INIT OFF)
+5 -2
View File
@@ -7,6 +7,9 @@
# find GNU sed to use `-i` parameter
SED:=$(shell command -v gsed || which sed)
# find GNU tar to use `--sort` and `--pax-option` parameters
TAR:=$(shell command -v gtar || which tar)
##########################################################################
# source files
@@ -215,8 +218,8 @@ ChangeLog.md:
# archive is created according to the advices of <https://reproducible-builds.org/docs/archives/>.
json.tar.xz:
mkdir json
rsync -R $(shell find LICENSE.MIT nlohmann_json.natvis CMakeLists.txt cmake/*.in include single_include -type f) json
gtar --sort=name --mtime="@$(shell git log -1 --pretty=%ct)" --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime --create --file - json | xz --compress -9e --threads=2 - > json.tar.xz
rsync -R $(shell find LICENSE.MIT nlohmann_json.natvis CMakeLists.txt cmake/*.in include single_include src/modules -type f) json
$(TAR) --sort=name --mtime="@$(shell git log -1 --pretty=%ct)" --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime --create --file - json | xz --compress -9e --threads=2 - > json.tar.xz
rm -fr json
# We use `-X` to make the resulting ZIP file reproducible, see
+12 -9
View File
@@ -1204,15 +1204,18 @@ language bindings, format converters, and the like. See the curated [Ecosystem](
Though it's 2026 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
- GCC 4.8 - 14.2 (and possibly later)
- Clang 3.4 - 21.0 (and possibly later)
- Apple Clang 9.1 - 16.0 (and possibly later)
- Intel C++ Compiler 17.0.2 (and possibly later)
- Nvidia CUDA Compiler 11.0.221 (and possibly later)
- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later)
- Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later)
- Microsoft Visual C++ 2019 / Build Tools 16.3.1+1def00d3d (and possibly later)
- Microsoft Visual C++ 2022 / Build Tools 19.30.30709.0 (and possibly later)
- GCC 4.8 - 16.2 (and possibly later)
- Clang 3.4 - 22.1 (and possibly later)
- Apple Clang 15.0 - 21.0 (and possibly later)
- Intel C++ Compiler Classic (icpc) 2021.10
- Intel oneAPI DPC++/C++ Compiler (icpx) 2025.3 (and possibly later)
- NVIDIA CUDA Compiler (nvcc) 11.8 - 12.6 (and possibly later)
- NVIDIA HPC SDK C++ Compiler (nvc++) 25.5 (and possibly later)
- Microsoft Visual C++ 2015 / MSVC 19.0 (and possibly later)
- Microsoft Visual C++ 2017 / MSVC 19.16 (and possibly later)
- Microsoft Visual C++ 2019 / MSVC 19.29 (and possibly later)
- Microsoft Visual C++ 2022 / MSVC 19.44 (and possibly later)
- Microsoft Visual C++ 2026 / MSVC 19.51 (and possibly later)
I would be happy to learn about other compilers/versions.
+1 -1
View File
@@ -125,7 +125,7 @@ automatically download a release as a dependency at configure time.
### `JSON_BuildTests`
Build the unit tests when [`BUILD_TESTING`](https://cmake.org/cmake/help/latest/command/enable_testing.html) is enabled. This option is `ON` by default if the library's CMake project is the top project. That is, when integrating the library as described above, the test suite is not built unless explicitly switched on with this option.
Build the unit tests when [`BUILD_TESTING`](https://cmake.org/cmake/help/latest/command/enable_testing.html) is enabled. This option is `ON` by default if the library's CMake project is the top project and the `tests` directory exists (the release archive `json.tar.xz` does not contain it). That is, when integrating the library as described above, the test suite is not built unless explicitly switched on with this option.
### `JSON_CI`
@@ -27,6 +27,7 @@
#include <nlohmann/detail/meta/identity_tag.hpp>
#include <nlohmann/detail/meta/std_fs.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/meta/logic.hpp>
#include <nlohmann/detail/string_concat.hpp>
#include <nlohmann/detail/value_t.hpp>
@@ -428,7 +429,9 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
}
// overload for arithmetic types, not chosen for basic_json template arguments
// (BooleanType, etc.)
// (BooleanType, etc.); note: Is it really necessary to provide explicit
// overloads for boolean_t etc. in case of a custom BooleanType which is not
// an arithmetic type?
template < typename BasicJsonType, typename ArithmeticType,
enable_if_t <
std::is_arithmetic<ArithmeticType>::value&&
@@ -524,7 +527,7 @@ inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priori
template<typename BasicJsonType, typename... Args>
std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
{
static_assert(conjunction<disjunction<negation<std::is_reference<Args>>, is_compatible_reference_type<BasicJsonType, Args>>...>::value,
static_assert(cxpr_and<cxpr_or<cxpr_not<std::is_reference<Args>>, is_compatible_reference_type<BasicJsonType, Args>>...>::value,
"Can not return a tuple containing references to types not contained in a Json, try Json::get_to()");
return from_json_tuple_impl_base<1, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
}
@@ -589,7 +592,7 @@ inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Has
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
// Workaround for MSVC 19.51 (and possibly later): in large cpp files, the compiler may fail to resolve with generic has_from_json (issue #4996)
// Workaround for MSVC 19.51 (and possibly later): in large in large cpp files, the compiler may fail to resolve with generic has_from_json (issue #4996)
template<typename BasicJsonType>
struct has_from_json<BasicJsonType, std_fs::path, void> : std::true_type {};
@@ -60,11 +60,9 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
"iter_impl only accepts (const) basic_json");
// superficial check for the LegacyBidirectionalIterator named requirement
// note: only array_t::iterator is checked here; object_t::iterator may be
// a forward-only iterator as long as reverse iteration and operator--
// are never used on it
static_assert(std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
"basic_json iterator assumes array type iterators satisfy the LegacyBidirectionalIterator named requirement.");
static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
&& std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
"basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
public:
/// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
+57
View File
@@ -583,6 +583,63 @@ class json_pointer
return *ptr;
}
/*!
@throw parse_error.106 if an array index begins with '0'
@throw parse_error.109 if an array index was not a number
@throw out_of_range.402 if the array index '-' is used
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
template<typename BasicJsonType>
const BasicJsonType& get_checked(const BasicJsonType* ptr) const
{
for (const auto& reference_token : reference_tokens)
{
switch (ptr->type())
{
case detail::value_t::object:
{
// note: at performs range check
ptr = &ptr->at(reference_token);
break;
}
case detail::value_t::array:
{
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" always fails the range check
JSON_THROW(detail::out_of_range::create(402, detail::concat(
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
") is out of range"), ptr));
}
const auto idx = array_index<BasicJsonType>(reference_token);
// Bounds check before access to avoid exception with JSON_NOEXCEPTION
if (JSON_HEDLEY_UNLIKELY(idx >= ptr->m_data.m_value.array->size()))
{
JSON_THROW(detail::out_of_range::create(401, detail::concat(
"array index ", std::to_string(idx), " is out of range"), ptr));
}
ptr = &ptr->operator[](idx);
break;
}
case detail::value_t::null:
case detail::value_t::string:
case detail::value_t::boolean:
case detail::value_t::number_integer:
case detail::value_t::number_unsigned:
case detail::value_t::number_float:
case detail::value_t::binary:
case detail::value_t::discarded:
default:
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
}
}
return *ptr;
}
/*!
@brief return a pointer to the pointed to value, or `nullptr` if the
pointer cannot be resolved because a key is missing, an array
+27 -4
View File
@@ -9,6 +9,7 @@
#pragma once
#include <utility> // declval, pair
#include <nlohmann/detail/meta/detected.hpp>
#include <nlohmann/thirdparty/hedley/hedley.hpp>
// This file contains all internal macro definitions (except those affecting ABI)
@@ -139,12 +140,10 @@
// libstdc++ < 11 has incomplete C++20 ranges (issue #4440)
#elif defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE < 11
#define JSON_HAS_RANGES 0
// clang < 16 with libstdc++ does not implement the ranges customization
// points libstdc++ declares, so its C++20 ranges support is incomplete (issue #5161)
// libc++ < 16 has incomplete C++20 ranges (issue #4440)
#elif defined(__clang__) && !defined(__apple_build_version__) \
&& __clang_major__ < 16 && defined(__GLIBCXX__)
#define JSON_HAS_RANGES 0
// libc++ < 16 has incomplete C++20 ranges (issue #4440)
#elif defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 160000
#define JSON_HAS_RANGES 0
// nvcc CUDA 12.0/12.1 chokes on the enable_borrowed_range variable-template
@@ -306,7 +305,7 @@ void templated_json_throw(ExceptionType exception)
@brief macro to briefly define a mapping between an enum and JSON with exception
on invalid input
@def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT
@since version 3.13.0
@since version 3.12.0
*/
#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \
template<typename BasicJsonType> \
@@ -877,6 +876,30 @@ void templated_json_throw(ExceptionType exception)
\
template<typename... T> \
using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
} \
\
namespace detail2 { \
struct std_name##_tag \
{ \
}; \
\
template<typename... T> \
std_name##_tag std_name(T&&...); \
\
template<typename... T> \
using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
\
template<typename... T> \
struct would_call_std_##std_name \
{ \
static constexpr auto const value = ::nlohmann::detail:: \
is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
}; \
} /* namespace detail2 */ \
\
template<typename... T> \
struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
{ \
}
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
@@ -12,6 +12,6 @@
NLOHMANN_JSON_NAMESPACE_BEGIN
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin)
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
NLOHMANN_JSON_NAMESPACE_END
@@ -12,6 +12,6 @@
NLOHMANN_JSON_NAMESPACE_BEGIN
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end)
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
NLOHMANN_JSON_NAMESPACE_END
@@ -62,5 +62,9 @@ using detected_or_t = typename detected_or<Default, Op, Args...>::type;
template<class Expected, template<class...> class Op, class... Args>
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
template<class To, template<class...> class Op, class... Args>
using is_detected_convertible =
std::is_convertible<detected_t<Op, Args...>, To>;
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
+34 -1
View File
@@ -8,7 +8,7 @@
#pragma once
#include <cstddef> // size_t
#include <cstdint> // size_t
#include <utility> // declval
#include <string> // string
@@ -70,6 +70,37 @@ using parse_error_function_t = decltype(std::declval<T&>().parse_error(
std::declval<std::size_t>(), std::declval<const std::string&>(),
std::declval<const Exception&>()));
template<typename SAX, typename BasicJsonType>
struct is_sax
{
private:
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using binary_t = typename BasicJsonType::binary_t;
using exception_t = typename BasicJsonType::exception;
public:
static constexpr bool value =
is_detected_exact<bool, null_function_t, SAX>::value &&
is_detected_exact<bool, boolean_function_t, SAX>::value &&
is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
is_detected_exact<bool, start_object_function_t, SAX>::value &&
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
is_detected_exact<bool, end_object_function_t, SAX>::value &&
is_detected_exact<bool, start_array_function_t, SAX>::value &&
is_detected_exact<bool, end_array_function_t, SAX>::value &&
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
};
template<typename SAX, typename BasicJsonType>
struct is_sax_static_asserts
{
@@ -89,6 +120,8 @@ struct is_sax_static_asserts
"Missing/invalid function: bool null()");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value,
+54
View File
@@ -0,0 +1,54 @@
#pragma once
#include <nlohmann/detail/macro_scope.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
#ifdef JSON_HAS_CPP_17
template<bool... Booleans>
struct cxpr_or_impl : std::integral_constant < bool, (Booleans || ...) > {};
template<bool... Booleans>
struct cxpr_and_impl : std::integral_constant < bool, (Booleans &&...) > {};
#else
template<bool... Booleans>
struct cxpr_or_impl : std::false_type {};
template<bool... Booleans>
struct cxpr_or_impl<true, Booleans...> : std::true_type {};
template<bool... Booleans>
struct cxpr_or_impl<false, Booleans...> : cxpr_or_impl<Booleans...> {};
template<bool... Booleans>
struct cxpr_and_impl : std::true_type {};
template<bool... Booleans>
struct cxpr_and_impl<true, Booleans...> : cxpr_and_impl<Booleans...> {};
template<bool... Booleans>
struct cxpr_and_impl<false, Booleans...> : std::false_type {};
#endif
template<class Boolean>
struct cxpr_not : std::integral_constant < bool, !Boolean::value > {};
template<class... Booleans>
struct cxpr_or : cxpr_or_impl<Booleans::value...> {};
template<bool... Booleans>
struct cxpr_or_c : cxpr_or_impl<Booleans...> {};
template<class... Booleans>
struct cxpr_and : cxpr_and_impl<Booleans::value...> {};
template<bool... Booleans>
struct cxpr_and_c : cxpr_and_impl<Booleans...> {};
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
+18 -9
View File
@@ -283,13 +283,6 @@ template<class B, class... Bn>
struct conjunction<B, Bn...>
: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
// https://en.cppreference.com/w/cpp/types/disjunction
template<class...> struct disjunction : std::false_type { };
template<class B> struct disjunction<B> : B { };
template<class B, class... Bn>
struct disjunction<B, Bn...>
: std::conditional<static_cast<bool>(B::value), B, disjunction<Bn...>>::type {};
// https://en.cppreference.com/w/cpp/types/negation
template<class B> struct negation : std::integral_constant < bool, !B::value > { };
@@ -611,6 +604,7 @@ struct is_compatible_integer_type_impl <
std::is_integral<CompatibleNumberIntegerType>::value&&
!std::is_same<bool, CompatibleNumberIntegerType>::value >>
{
// is there an assert somewhere on overflows?
using RealLimits = std::numeric_limits<RealIntegerType>;
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
@@ -804,7 +798,20 @@ struct has_capacity : std::integral_constant<bool, is_detected<detect_capacity,
// a naive helper to check if a type is an ordered_map (exploits the fact that
// ordered_map inherits capacity() from std::vector)
template <typename T>
struct is_ordered_map : has_capacity<T> {};
struct is_ordered_map
{
using one = char;
struct two
{
char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
};
template <typename C> static one test( decltype(&C::capacity) ) ;
template <typename C> static two test(...);
enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg,cppcoreguidelines-use-enum-class)
};
// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
@@ -828,8 +835,10 @@ using all_signed = conjunction<std::is_signed<Types>...>;
template<typename... Types>
using all_unsigned = conjunction<std::is_unsigned<Types>...>;
// there's a disjunction trait in another PR; replace when merged
template<typename... Types>
using same_sign = disjunction<all_signed<Types...>, all_unsigned<Types...>>;
using same_sign = std::integral_constant < bool,
all_signed<Types...>::value || all_unsigned<Types...>::value >;
template<typename OfType, typename T>
using never_out_of_range = std::integral_constant < bool,
+300 -116
View File
@@ -275,6 +275,104 @@
#include <utility> // declval, pair
// #include <nlohmann/detail/meta/detected.hpp>
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include <type_traits>
// #include <nlohmann/detail/meta/void_t.hpp>
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
// #include <nlohmann/detail/abi_macros.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
template<typename ...Ts> struct make_void
{
using type = void;
};
template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
// https://en.cppreference.com/w/cpp/experimental/is_detected
struct nonesuch
{
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
nonesuch(nonesuch const&&) = delete;
void operator=(nonesuch const&) = delete;
void operator=(nonesuch&&) = delete;
};
template<class Default,
class AlwaysVoid,
template<class...> class Op,
class... Args>
struct detector
{
using value_t = std::false_type;
using type = Default;
};
template<class Default, template<class...> class Op, class... Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
{
using value_t = std::true_type;
using type = Op<Args...>;
};
template<template<class...> class Op, class... Args>
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
template<template<class...> class Op, class... Args>
struct is_detected_lazy : is_detected<Op, Args...> { };
template<template<class...> class Op, class... Args>
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
template<class Default, template<class...> class Op, class... Args>
using detected_or = detector<Default, void, Op, Args...>;
template<class Default, template<class...> class Op, class... Args>
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
template<class Expected, template<class...> class Op, class... Args>
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
template<class To, template<class...> class Op, class... Args>
using is_detected_convertible =
std::is_convertible<detected_t<Op, Args...>, To>;
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/thirdparty/hedley/hedley.hpp>
@@ -2453,12 +2551,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP
// libstdc++ < 11 has incomplete C++20 ranges (issue #4440)
#elif defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE < 11
#define JSON_HAS_RANGES 0
// clang < 16 with libstdc++ does not implement the ranges customization
// points libstdc++ declares, so its C++20 ranges support is incomplete (issue #5161)
// libc++ < 16 has incomplete C++20 ranges (issue #4440)
#elif defined(__clang__) && !defined(__apple_build_version__) \
&& __clang_major__ < 16 && defined(__GLIBCXX__)
#define JSON_HAS_RANGES 0
// libc++ < 16 has incomplete C++20 ranges (issue #4440)
#elif defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 160000
#define JSON_HAS_RANGES 0
// nvcc CUDA 12.0/12.1 chokes on the enable_borrowed_range variable-template
@@ -2620,7 +2716,7 @@ void templated_json_throw(ExceptionType exception)
@brief macro to briefly define a mapping between an enum and JSON with exception
on invalid input
@def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT
@since version 3.13.0
@since version 3.12.0
*/
#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \
template<typename BasicJsonType> \
@@ -3191,6 +3287,30 @@ void templated_json_throw(ExceptionType exception)
\
template<typename... T> \
using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
} \
\
namespace detail2 { \
struct std_name##_tag \
{ \
}; \
\
template<typename... T> \
std_name##_tag std_name(T&&...); \
\
template<typename... T> \
using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
\
template<typename... T> \
struct would_call_std_##std_name \
{ \
static constexpr auto const value = ::nlohmann::detail:: \
is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
}; \
} /* namespace detail2 */ \
\
template<typename... T> \
struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
{ \
}
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
@@ -3740,31 +3860,6 @@ NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/abi_macros.hpp>
// #include <nlohmann/detail/meta/void_t.hpp>
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
// #include <nlohmann/detail/abi_macros.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
template<typename ...Ts> struct make_void
{
using type = void;
};
template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/meta/cpp_future.hpp>
@@ -3836,7 +3931,7 @@ NLOHMANN_JSON_NAMESPACE_END
NLOHMANN_JSON_NAMESPACE_BEGIN
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin)
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
NLOHMANN_JSON_NAMESPACE_END
@@ -3856,80 +3951,13 @@ NLOHMANN_JSON_NAMESPACE_END
NLOHMANN_JSON_NAMESPACE_BEGIN
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end)
NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/meta/cpp_future.hpp>
// #include <nlohmann/detail/meta/detected.hpp>
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include <type_traits>
// #include <nlohmann/detail/meta/void_t.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
// https://en.cppreference.com/w/cpp/experimental/is_detected
struct nonesuch
{
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
nonesuch(nonesuch const&&) = delete;
void operator=(nonesuch const&) = delete;
void operator=(nonesuch&&) = delete;
};
template<class Default,
class AlwaysVoid,
template<class...> class Op,
class... Args>
struct detector
{
using value_t = std::false_type;
using type = Default;
};
template<class Default, template<class...> class Op, class... Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
{
using value_t = std::true_type;
using type = Op<Args...>;
};
template<template<class...> class Op, class... Args>
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
template<template<class...> class Op, class... Args>
struct is_detected_lazy : is_detected<Op, Args...> { };
template<template<class...> class Op, class... Args>
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
template<class Default, template<class...> class Op, class... Args>
using detected_or = detector<Default, void, Op, Args...>;
template<class Default, template<class...> class Op, class... Args>
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
template<class Expected, template<class...> class Op, class... Args>
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/json_fwd.hpp>
// __ _____ _____ _____
@@ -4265,13 +4293,6 @@ template<class B, class... Bn>
struct conjunction<B, Bn...>
: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
// https://en.cppreference.com/w/cpp/types/disjunction
template<class...> struct disjunction : std::false_type { };
template<class B> struct disjunction<B> : B { };
template<class B, class... Bn>
struct disjunction<B, Bn...>
: std::conditional<static_cast<bool>(B::value), B, disjunction<Bn...>>::type {};
// https://en.cppreference.com/w/cpp/types/negation
template<class B> struct negation : std::integral_constant < bool, !B::value > { };
@@ -4593,6 +4614,7 @@ struct is_compatible_integer_type_impl <
std::is_integral<CompatibleNumberIntegerType>::value&&
!std::is_same<bool, CompatibleNumberIntegerType>::value >>
{
// is there an assert somewhere on overflows?
using RealLimits = std::numeric_limits<RealIntegerType>;
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
@@ -4786,7 +4808,20 @@ struct has_capacity : std::integral_constant<bool, is_detected<detect_capacity,
// a naive helper to check if a type is an ordered_map (exploits the fact that
// ordered_map inherits capacity() from std::vector)
template <typename T>
struct is_ordered_map : has_capacity<T> {};
struct is_ordered_map
{
using one = char;
struct two
{
char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
};
template <typename C> static one test( decltype(&C::capacity) ) ;
template <typename C> static two test(...);
enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg,cppcoreguidelines-use-enum-class)
};
// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
@@ -4810,8 +4845,10 @@ using all_signed = conjunction<std::is_signed<Types>...>;
template<typename... Types>
using all_unsigned = conjunction<std::is_unsigned<Types>...>;
// there's a disjunction trait in another PR; replace when merged
template<typename... Types>
using same_sign = disjunction<all_signed<Types...>, all_unsigned<Types...>>;
using same_sign = std::integral_constant < bool,
all_signed<Types...>::value || all_unsigned<Types...>::value >;
template<typename OfType, typename T>
using never_out_of_range = std::integral_constant < bool,
@@ -5429,6 +5466,63 @@ NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/meta/type_traits.hpp>
// #include <nlohmann/detail/meta/logic.hpp>
// #include <nlohmann/detail/macro_scope.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
#ifdef JSON_HAS_CPP_17
template<bool... Booleans>
struct cxpr_or_impl : std::integral_constant < bool, (Booleans || ...) > {};
template<bool... Booleans>
struct cxpr_and_impl : std::integral_constant < bool, (Booleans &&...) > {};
#else
template<bool... Booleans>
struct cxpr_or_impl : std::false_type {};
template<bool... Booleans>
struct cxpr_or_impl<true, Booleans...> : std::true_type {};
template<bool... Booleans>
struct cxpr_or_impl<false, Booleans...> : cxpr_or_impl<Booleans...> {};
template<bool... Booleans>
struct cxpr_and_impl : std::true_type {};
template<bool... Booleans>
struct cxpr_and_impl<true, Booleans...> : cxpr_and_impl<Booleans...> {};
template<bool... Booleans>
struct cxpr_and_impl<false, Booleans...> : std::false_type {};
#endif
template<class Boolean>
struct cxpr_not : std::integral_constant < bool, !Boolean::value > {};
template<class... Booleans>
struct cxpr_or : cxpr_or_impl<Booleans::value...> {};
template<bool... Booleans>
struct cxpr_or_c : cxpr_or_impl<Booleans...> {};
template<class... Booleans>
struct cxpr_and : cxpr_and_impl<Booleans::value...> {};
template<bool... Booleans>
struct cxpr_and_c : cxpr_and_impl<Booleans...> {};
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/string_concat.hpp>
// #include <nlohmann/detail/value_t.hpp>
@@ -5832,7 +5926,9 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
}
// overload for arithmetic types, not chosen for basic_json template arguments
// (BooleanType, etc.)
// (BooleanType, etc.); note: Is it really necessary to provide explicit
// overloads for boolean_t etc. in case of a custom BooleanType which is not
// an arithmetic type?
template < typename BasicJsonType, typename ArithmeticType,
enable_if_t <
std::is_arithmetic<ArithmeticType>::value&&
@@ -5928,7 +6024,7 @@ inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priori
template<typename BasicJsonType, typename... Args>
std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
{
static_assert(conjunction<disjunction<negation<std::is_reference<Args>>, is_compatible_reference_type<BasicJsonType, Args>>...>::value,
static_assert(cxpr_and<cxpr_or<cxpr_not<std::is_reference<Args>>, is_compatible_reference_type<BasicJsonType, Args>>...>::value,
"Can not return a tuple containing references to types not contained in a Json, try Json::get_to()");
return from_json_tuple_impl_base<1, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
}
@@ -5993,7 +6089,7 @@ inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Has
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
// Workaround for MSVC 19.51 (and possibly later): in large cpp files, the compiler may fail to resolve with generic has_from_json (issue #4996)
// Workaround for MSVC 19.51 (and possibly later): in large in large cpp files, the compiler may fail to resolve with generic has_from_json (issue #4996)
template<typename BasicJsonType>
struct has_from_json<BasicJsonType, std_fs::path, void> : std::true_type {};
@@ -12545,7 +12641,7 @@ NLOHMANN_JSON_NAMESPACE_END
#include <cstddef> // size_t
#include <cstdint> // size_t
#include <utility> // declval
#include <string> // string
@@ -12610,6 +12706,37 @@ using parse_error_function_t = decltype(std::declval<T&>().parse_error(
std::declval<std::size_t>(), std::declval<const std::string&>(),
std::declval<const Exception&>()));
template<typename SAX, typename BasicJsonType>
struct is_sax
{
private:
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using binary_t = typename BasicJsonType::binary_t;
using exception_t = typename BasicJsonType::exception;
public:
static constexpr bool value =
is_detected_exact<bool, null_function_t, SAX>::value &&
is_detected_exact<bool, boolean_function_t, SAX>::value &&
is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
is_detected_exact<bool, start_object_function_t, SAX>::value &&
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
is_detected_exact<bool, end_object_function_t, SAX>::value &&
is_detected_exact<bool, start_array_function_t, SAX>::value &&
is_detected_exact<bool, end_array_function_t, SAX>::value &&
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
};
template<typename SAX, typename BasicJsonType>
struct is_sax_static_asserts
{
@@ -12629,6 +12756,8 @@ struct is_sax_static_asserts
"Missing/invalid function: bool null()");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value,
@@ -17810,11 +17939,9 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
"iter_impl only accepts (const) basic_json");
// superficial check for the LegacyBidirectionalIterator named requirement
// note: only array_t::iterator is checked here; object_t::iterator may be
// a forward-only iterator as long as reverse iteration and operator--
// are never used on it
static_assert(std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
"basic_json iterator assumes array type iterators satisfy the LegacyBidirectionalIterator named requirement.");
static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
&& std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
"basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
public:
/// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
@@ -19298,6 +19425,63 @@ class json_pointer
return *ptr;
}
/*!
@throw parse_error.106 if an array index begins with '0'
@throw parse_error.109 if an array index was not a number
@throw out_of_range.402 if the array index '-' is used
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
template<typename BasicJsonType>
const BasicJsonType& get_checked(const BasicJsonType* ptr) const
{
for (const auto& reference_token : reference_tokens)
{
switch (ptr->type())
{
case detail::value_t::object:
{
// note: at performs range check
ptr = &ptr->at(reference_token);
break;
}
case detail::value_t::array:
{
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" always fails the range check
JSON_THROW(detail::out_of_range::create(402, detail::concat(
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
") is out of range"), ptr));
}
const auto idx = array_index<BasicJsonType>(reference_token);
// Bounds check before access to avoid exception with JSON_NOEXCEPTION
if (JSON_HEDLEY_UNLIKELY(idx >= ptr->m_data.m_value.array->size()))
{
JSON_THROW(detail::out_of_range::create(401, detail::concat(
"array index ", std::to_string(idx), " is out of range"), ptr));
}
ptr = &ptr->operator[](idx);
break;
}
case detail::value_t::null:
case detail::value_t::string:
case detail::value_t::boolean:
case detail::value_t::number_integer:
case detail::value_t::number_unsigned:
case detail::value_t::number_float:
case detail::value_t::binary:
case detail::value_t::discarded:
default:
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
}
}
return *ptr;
}
/*!
@brief return a pointer to the pointed to value, or `nullptr` if the
pointer cannot be resolved because a key is missing, an array
-12
View File
@@ -10,14 +10,10 @@
#if JSON_TEST_USING_MULTIPLE_HEADERS
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/ordered_map.hpp>
#else
#include <nlohmann/json.hpp>
#endif
#include <map>
#include <string>
TEST_CASE("type traits")
{
SECTION("is_c_string")
@@ -87,12 +83,4 @@ TEST_CASE("type traits")
}
}
}
SECTION("is_ordered_map")
{
using nlohmann::detail::is_ordered_map;
CHECK(is_ordered_map<nlohmann::ordered_map<std::string, int>>::value);
CHECK_FALSE(is_ordered_map<std::map<std::string, int>>::value);
}
}