Merge branch 'develop' of https://github.com/nlohmann/json into issue2286

 Conflicts:
	single_include/nlohmann/json.hpp
This commit is contained in:
Niels Lohmann 2020-07-25 21:44:58 +02:00
commit 42f8708940
No known key found for this signature in database
GPG key ID: 7F3CEA63AE251B69
22 changed files with 2770 additions and 2785 deletions

3
.gitignore vendored
View file

@ -22,7 +22,7 @@ benchmarks/files/numbers/*.json
.wsjcpp/*
.idea
cmake-build-debug
/cmake-build-*
test/test-*
/.vs
@ -32,3 +32,4 @@ doc/mkdocs/docs/images
doc/mkdocs/docs/examples
doc/mkdocs/site
doc/mkdocs/docs/__pycache__/
doc/xml

View file

@ -24,7 +24,7 @@ endif ()
option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON)
option(JSON_Install "Install CMake targets during install step." ON)
option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF)
option(JSON_ImplicitConversions "Enable implicit conversions" ON)
option(JSON_ImplicitConversions "Enable implicit conversions." ON)
##
## CONFIGURATION
@ -49,6 +49,10 @@ else()
message(STATUS "Using the single-header code from ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}")
endif()
if (NOT JSON_ImplicitConversions)
message(STATUS "Implicit conversions are disabled")
endif()
##
## TARGET
## create target and add include path

View file

@ -54,13 +54,13 @@ all:
##########################################################################
coverage:
rm -fr build_coverage
mkdir build_coverage
cd build_coverage ; cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON
cd build_coverage ; ninja
cd build_coverage ; ctest -j10
cd build_coverage ; ninja lcov_html
open build_coverage/test/html/index.html
rm -fr cmake-build-coverage
mkdir cmake-build-coverage
cd cmake-build-coverage ; cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON
cd cmake-build-coverage ; ninja
cd cmake-build-coverage ; ctest -j10
cd cmake-build-coverage ; ninja lcov_html
open cmake-build-coverage/test/html/index.html
##########################################################################
# documentation tests
@ -88,7 +88,7 @@ doctest:
# -Wno-switch-enum -Wno-covered-switch-default: pedantic/contradicting warnings about switches
# -Wno-weak-vtables: exception class is defined inline, but has virtual method
pedantic_clang:
rm -fr build_pedantic
rm -fr cmake-build-pedantic
CXXFLAGS=" \
-std=c++11 -Wno-c++98-compat -Wno-c++98-compat-pedantic \
-Werror \
@ -103,12 +103,12 @@ pedantic_clang:
-Wno-padded \
-Wno-range-loop-analysis \
-Wno-switch-enum -Wno-covered-switch-default \
-Wno-weak-vtables" cmake -S . -B build_pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On
cmake --build build_pedantic
-Wno-weak-vtables" cmake -S . -B cmake-build-pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On
cmake --build cmake-build-pedantic
# calling GCC with most warnings
pedantic_gcc:
rm -fr build_pedantic
rm -fr cmake-build-pedantic
CXXFLAGS=" \
-std=c++11 \
-pedantic \
@ -366,19 +366,19 @@ pedantic_gcc:
-Wwrite-strings \
-Wzero-as-null-pointer-constant \
-Wzero-length-bounds \
" cmake -S . -B build_pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On
cmake --build build_pedantic
" cmake -S . -B cmake-build-pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On
cmake --build cmake-build-pedantic
##########################################################################
# benchmarks
##########################################################################
run_benchmarks:
rm -fr build_benchmarks
mkdir build_benchmarks
cd build_benchmarks ; cmake ../benchmarks -GNinja -DCMAKE_BUILD_TYPE=Release -DJSON_BuildTests=On
cd build_benchmarks ; ninja
cd build_benchmarks ; ./json_benchmarks
rm -fr cmake-build-benchmarks
mkdir cmake-build-benchmarks
cd cmake-build-benchmarks ; cmake ../benchmarks -GNinja -DCMAKE_BUILD_TYPE=Release -DJSON_BuildTests=On
cd cmake-build-benchmarks ; ninja
cd cmake-build-benchmarks ; ./json_benchmarks
##########################################################################
# fuzzing
@ -451,14 +451,14 @@ cppcheck:
# call Clang Static Analyzer <https://clang-analyzer.llvm.org>
clang_analyze:
rm -fr clang_analyze_build
mkdir clang_analyze_build
cd clang_analyze_build ; CCC_CXX=$(COMPILER_DIR)/clang++ CXX=$(COMPILER_DIR)/clang++ $(COMPILER_DIR)/scan-build cmake .. -GNinja -DJSON_BuildTests=On
cd clang_analyze_build ; \
rm -fr cmake-build-clang-analyze
mkdir cmake-build-clang-analyze
cd cmake-build-clang-analyze ; CCC_CXX=$(COMPILER_DIR)/clang++ CXX=$(COMPILER_DIR)/clang++ $(COMPILER_DIR)/scan-build cmake .. -GNinja -DJSON_BuildTests=On
cd cmake-build-clang-analyze ; \
$(COMPILER_DIR)/scan-build \
-enable-checker alpha.core.BoolAssignment,alpha.core.CallAndMessageUnInitRefArg,alpha.core.CastSize,alpha.core.CastToStruct,alpha.core.Conversion,alpha.core.DynamicTypeChecker,alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,alpha.core.SizeofPtr,alpha.core.StackAddressAsyncEscape,alpha.core.TestAfterDivZero,alpha.deadcode.UnreachableCode,core.builtin.BuiltinFunctions,core.builtin.NoReturnFunctions,core.CallAndMessage,core.DivideZero,core.DynamicTypePropagation,core.NonnilStringConstants,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,core.VLASize,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.SelfAssignment,deadcode.DeadStores,nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull \
--use-c++=$(COMPILER_DIR)/clang++ -analyze-headers -o report ninja
open clang_analyze_build/report/*/index.html
open cmake-build-clang-analyze/report/*/index.html
# call cpplint <https://github.com/cpplint/cpplint>
# Note: some errors expected due to false positives
@ -473,18 +473,18 @@ clang_tidy:
# call PVS-Studio Analyzer <https://www.viva64.com/en/pvs-studio/>
pvs_studio:
rm -fr pvs_studio_build
mkdir pvs_studio_build
cd pvs_studio_build ; cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DJSON_MultipleHeaders=ON
cd pvs_studio_build ; pvs-studio-analyzer analyze -j 10
cd pvs_studio_build ; plog-converter -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs
open pvs_studio_build/pvs/index.html
rm -fr cmake-build-pvs-studio
mkdir cmake-build-pvs-studio
cd cmake-build-pvs-studio ; cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DJSON_MultipleHeaders=ON
cd cmake-build-pvs-studio ; pvs-studio-analyzer analyze -j 10
cd cmake-build-pvs-studio ; plog-converter -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs
open cmake-build-pvs-studio/pvs/index.html
# call Infer <https://fbinfer.com> static analyzer
infer:
rm -fr infer_build
mkdir infer_build
cd infer_build ; infer compile -- cmake .. -DJSON_MultipleHeaders=ON ; infer run -- make -j 4
rm -fr cmake-build-infer
mkdir cmake-build-infer
cd cmake-build-infer ; infer compile -- cmake .. -DJSON_MultipleHeaders=ON ; infer run -- make -j 4
# call OCLint <http://oclint.org> static analyzer
oclint:
@ -493,11 +493,11 @@ oclint:
# execute the test suite with Clang sanitizers (address and undefined behavior)
clang_sanitize:
rm -fr clang_sanitize_build
mkdir clang_sanitize_build
cd clang_sanitize_build ; CXX=$(COMPILER_DIR)/clang++ cmake .. -DJSON_Sanitizer=On -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On -GNinja
cd clang_sanitize_build ; ninja
cd clang_sanitize_build ; ctest -j10
rm -fr cmake-build-clang-sanitize
mkdir cmake-build-clang-sanitize
cd cmake-build-clang-sanitize ; CXX=$(COMPILER_DIR)/clang++ cmake .. -DJSON_Sanitizer=On -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On -GNinja
cd cmake-build-clang-sanitize ; ninja
cd cmake-build-clang-sanitize ; ctest -j10
##########################################################################
@ -525,7 +525,7 @@ pretty:
--preserve-date \
--suffix=none \
--formatted \
$(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp benchmarks/src/benchmarks.cpp doc/examples/*.cpp
$(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp test/utils/*.hpp benchmarks/src/benchmarks.cpp doc/examples/*.cpp
# create single header file
amalgamate: $(AMALGAMATED_FILE)
@ -625,7 +625,7 @@ clean:
rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM test/*.dSYM oclint_report.html
rm -fr benchmarks/files/numbers/*.json
rm -fr cmake-3.1.0-Darwin64.tar.gz cmake-3.1.0-Darwin64
rm -fr build_coverage build_benchmarks fuzz-testing clang_analyze_build pvs_studio_build infer_build clang_sanitize_build cmake_build
rm -fr cmake-build-coverage cmake-build-benchmarks fuzz-testing cmake-build-clang-analyze cmake-build-pvs-studio cmake-build-infer cmake-build-clang-sanitize cmake_build
$(MAKE) clean -Cdoc
##########################################################################

View file

@ -762,6 +762,7 @@ Supported types can be implicitly converted to JSON values.
It is recommended to **NOT USE** implicit conversions **FROM** a JSON value.
You can find more details about this recommendation [here](https://www.github.com/nlohmann/json/issues/958).
You can switch off implicit conversions by defining `JSON_USE_IMPLICIT_CONVERSIONS` to `0` before including the `json.hpp` header. When using CMake, you can also achieve this by setting the option `JSON_ImplicitConversions` to `OFF`.
```cpp
// strings

View file

@ -92,6 +92,10 @@ There are two macros to make your life easier as long as you (1) want to use a J
In both macros, the first parameter is the name of the class/struct, and all remaining parameters name the members.
!!! note
At most 64 member variables can be passed to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` or `NLOHMANN_DEFINE_TYPE_INTRUSIVE`.
??? example
The `to_json`/`from_json` functions for the `person` struct above can be created with:

View file

@ -32,6 +32,26 @@ This macro overrides `#!cpp try` calls inside the library. It has no arguments a
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
## `JSON_USE_IMPLICIT_CONVERSIONS`
When defined to `0`, implicit conversions are switched off. By default, implicit conversions are switched on.
??? example
This is an example for an implicit conversion:
```cpp
json j = "Hello, world!";
std::string s = j;
```
When `JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`, the code above does no longer compile. Instead, it must be written like this:
```cpp
json j = "Hello, world!";
auto s = j.get<std::string>();
```
## `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)`
This macro can be used to simplify the serialization/deserialization of types if (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object.

View file

@ -394,14 +394,14 @@ class binary_reader
/*!
@param[in] get_char whether a new character should be retrieved from the
input (true, default) or whether the last read
character should be considered instead
input (true) or whether the last read character should
be considered instead (false)
@param[in] tag_handler how CBOR tags should be treated
@return whether a valid CBOR value was passed to the SAX parser
*/
bool parse_cbor_internal(const bool get_char = true,
cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
bool parse_cbor_internal(const bool get_char,
const cbor_tag_handler_t tag_handler)
{
switch (get_char ? get() : current)
{
@ -607,34 +607,34 @@ class binary_reader
case 0x95:
case 0x96:
case 0x97:
return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
case 0x98: // array (one-byte uint8_t for n follows)
{
std::uint8_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
}
case 0x99: // array (two-byte uint16_t for n follow)
{
std::uint16_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
}
case 0x9A: // array (four-byte uint32_t for n follow)
{
std::uint32_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
}
case 0x9B: // array (eight-byte uint64_t for n follow)
{
std::uint64_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
}
case 0x9F: // array (indefinite length)
return get_cbor_array(std::size_t(-1));
return get_cbor_array(std::size_t(-1), tag_handler);
// map (0x00..0x17 pairs of data items follow)
case 0xA0:
@ -661,34 +661,34 @@ class binary_reader
case 0xB5:
case 0xB6:
case 0xB7:
return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
case 0xB8: // map (one-byte uint8_t for n follows)
{
std::uint8_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
}
case 0xB9: // map (two-byte uint16_t for n follow)
{
std::uint16_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
}
case 0xBA: // map (four-byte uint32_t for n follow)
{
std::uint32_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
}
case 0xBB: // map (eight-byte uint64_t for n follow)
{
std::uint64_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
}
case 0xBF: // map (indefinite length)
return get_cbor_object(std::size_t(-1));
return get_cbor_object(std::size_t(-1), tag_handler);
case 0xC6: // tagged item
case 0xC7:
@ -1031,9 +1031,11 @@ class binary_reader
/*!
@param[in] len the length of the array or std::size_t(-1) for an
array of indefinite size
@param[in] tag_handler how CBOR tags should be treated
@return whether array creation completed
*/
bool get_cbor_array(const std::size_t len)
bool get_cbor_array(const std::size_t len,
const cbor_tag_handler_t tag_handler)
{
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
{
@ -1044,7 +1046,7 @@ class binary_reader
{
for (std::size_t i = 0; i < len; ++i)
{
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal()))
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
{
return false;
}
@ -1054,7 +1056,7 @@ class binary_reader
{
while (get() != 0xFF)
{
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false)))
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
{
return false;
}
@ -1067,9 +1069,11 @@ class binary_reader
/*!
@param[in] len the length of the object or std::size_t(-1) for an
object of indefinite size
@param[in] tag_handler how CBOR tags should be treated
@return whether object creation completed
*/
bool get_cbor_object(const std::size_t len)
bool get_cbor_object(const std::size_t len,
const cbor_tag_handler_t tag_handler)
{
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
{
@ -1087,7 +1091,7 @@ class binary_reader
return false;
}
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal()))
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
{
return false;
}
@ -1103,7 +1107,7 @@ class binary_reader
return false;
}
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal()))
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
{
return false;
}

View file

@ -264,8 +264,8 @@
#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
#define NLOHMANN_JSON_TO(v1) j[#v1] = t.v1;
#define NLOHMANN_JSON_FROM(v1) j.at(#v1).get_to(t.v1);
#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
/*!
@brief macro
@ -273,8 +273,8 @@
@since version 3.9.0
*/
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
friend void to_json(nlohmann::json& j, const Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
friend void from_json(const nlohmann::json& j, Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
/*!
@brief macro
@ -282,8 +282,8 @@
@since version 3.9.0
*/
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
void to_json(nlohmann::json& j, const Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
void from_json(const nlohmann::json& j, Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
#define JSON_USE_IMPLICIT_CONVERSIONS 1

File diff suppressed because it is too large Load diff

View file

@ -151,7 +151,7 @@ foreach(file ${files})
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-deprecated;-Wno-float-equal>
$<$<CXX_COMPILER_ID:GNU>:-Wno-deprecated-declarations>
)
target_include_directories(${testcase} PRIVATE ${CMAKE_BINARY_DIR}/include thirdparty/doctest thirdparty/fifo_map)
target_include_directories(${testcase} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/utils ${CMAKE_BINARY_DIR}/include thirdparty/doctest thirdparty/fifo_map)
target_link_libraries(${testcase} PRIVATE ${NLOHMANN_JSON_TARGET_NAME})
if (JSON_Coverage)

View file

@ -0,0 +1,3 @@
#include "Bar.hpp"
class Bar;

View file

@ -0,0 +1,4 @@
#include <nlohmann/json.hpp>
#include "Foo.hpp"
class Bar : public Foo{};

View file

@ -9,3 +9,13 @@ set_target_properties(with_private_target PROPERTIES CXX_STANDARD 11)
add_executable(with_private_system_target main.cpp)
target_include_directories(with_private_system_target PRIVATE SYSTEM ${nlohmann_json_source}/include)
set_target_properties(with_private_system_target PROPERTIES CXX_STANDARD 11)
# regression from https://github.com/nlohmann/json/discussions/2281
add_library(Foo STATIC Foo.cpp Bar.cpp)
target_include_directories(Foo PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${nlohmann_json_source}/include)
set_target_properties(Foo PROPERTIES CXX_STANDARD 11)
add_library(Bar STATIC Bar.cpp)
target_link_libraries(Bar PRIVATE Foo)
target_include_directories(Bar PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${nlohmann_json_source}/include)
set_target_properties(Bar PROPERTIES CXX_STANDARD 11)

View file

@ -0,0 +1,3 @@
#include "Foo.hpp"
class Foo;

View file

@ -0,0 +1,4 @@
#pragma once
#include <nlohmann/json.hpp>
class Foo{};

View file

@ -35,6 +35,7 @@ using nlohmann::json;
#include <fstream>
#include <sstream>
#include <test_data.hpp>
#include <test_utils.hpp>
TEST_CASE("BSON")
{
@ -1263,10 +1264,7 @@ TEST_CASE("BSON roundtrips" * doctest::skip())
json j1 = json::parse(f_json);
// parse BSON file
std::ifstream f_bson(filename + ".bson", std::ios::binary);
std::vector<std::uint8_t> packed(
(std::istreambuf_iterator<char>(f_bson)),
std::istreambuf_iterator<char>());
auto packed = utils::read_binary_file(filename + ".bson");
json j2;
CHECK_NOTHROW(j2 = json::from_bson(packed));
@ -1296,10 +1294,7 @@ TEST_CASE("BSON roundtrips" * doctest::skip())
json j1 = json::parse(f_json);
// parse BSON file
std::ifstream f_bson(filename + ".bson", std::ios::binary);
std::vector<std::uint8_t> packed(
(std::istreambuf_iterator<char>(f_bson)),
std::istreambuf_iterator<char>());
auto packed = utils::read_binary_file(filename + ".bson");
json j2;
CHECK_NOTHROW(j2 = json::from_bson({packed.data(), packed.size()}));
@ -1314,10 +1309,7 @@ TEST_CASE("BSON roundtrips" * doctest::skip())
json j1 = json::parse(f_json);
// parse BSON file
std::ifstream f_bson(filename + ".bson", std::ios::binary);
std::vector<std::uint8_t> packed(
(std::istreambuf_iterator<char>(f_bson)),
std::istreambuf_iterator<char>());
auto packed = utils::read_binary_file(filename + ".bson");
{
INFO_WITH_TEMP(filename + ": output adapters: std::vector<std::uint8_t>");

View file

@ -39,6 +39,7 @@ using nlohmann::json;
#include <iostream>
#include <set>
#include <test_data.hpp>
#include <test_utils.hpp>
namespace
{
@ -1920,9 +1921,7 @@ TEST_CASE("single CBOR roundtrip")
json j1 = json::parse(f_json);
// parse CBOR file
std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_cbor)),
std::istreambuf_iterator<char>());
auto packed = utils::read_binary_file(filename + ".cbor");
json j2;
CHECK_NOTHROW(j2 = json::from_cbor(packed));
@ -1994,10 +1993,7 @@ TEST_CASE("CBOR regressions")
try
{
// parse CBOR file
std::ifstream f_cbor(filename, std::ios::binary);
std::vector<uint8_t> vec1(
(std::istreambuf_iterator<char>(f_cbor)),
std::istreambuf_iterator<char>());
auto vec1 = utils::read_binary_file(filename);
json j1 = json::from_cbor(vec1);
try
@ -2204,10 +2200,7 @@ TEST_CASE("CBOR roundtrips" * doctest::skip())
json j1 = json::parse(f_json);
// parse CBOR file
std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
std::vector<uint8_t> packed(
(std::istreambuf_iterator<char>(f_cbor)),
std::istreambuf_iterator<char>());
auto packed = utils::read_binary_file(filename + ".cbor");
json j2;
CHECK_NOTHROW(j2 = json::from_cbor(packed));
@ -2237,10 +2230,7 @@ TEST_CASE("CBOR roundtrips" * doctest::skip())
json j1 = json::parse(f_json);
// parse CBOR file
std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
std::vector<uint8_t> packed(
(std::istreambuf_iterator<char>(f_cbor)),
std::istreambuf_iterator<char>());
auto packed = utils::read_binary_file(filename + ".cbor");
json j2;
CHECK_NOTHROW(j2 = json::from_cbor({packed.data(), packed.size()}));
@ -2255,10 +2245,7 @@ TEST_CASE("CBOR roundtrips" * doctest::skip())
json j1 = json::parse(f_json);
// parse CBOR file
std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
std::vector<uint8_t> packed(
(std::istreambuf_iterator<char>(f_cbor)),
std::istreambuf_iterator<char>());
auto packed = utils::read_binary_file(filename + ".cbor");
if (!exclude_packed.count(filename))
{
@ -2493,15 +2480,11 @@ TEST_CASE("examples from RFC 7049 Appendix A")
SECTION("byte arrays")
{
std::ifstream f_cbor(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.cbor", std::ios::binary);
std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_cbor)),
std::istreambuf_iterator<char>());
auto packed = utils::read_binary_file(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.cbor");
json j;
CHECK_NOTHROW(j = json::from_cbor(packed));
std::ifstream f_bin(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.out", std::ios::binary);
std::vector<uint8_t> expected((std::istreambuf_iterator<char>(f_bin)),
std::istreambuf_iterator<char>());
auto expected = utils::read_binary_file(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.out");
CHECK(j == json::binary(expected));
CHECK(json::to_cbor(json::binary(std::vector<uint8_t> {}, 0x42)) == std::vector<uint8_t> {0xd8, 0x42, 0x40});
@ -2722,4 +2705,25 @@ TEST_CASE("Tagged values")
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
}
}
SECTION("tagged binary")
{
// create a binary value of subtype 42
json j;
j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42);
// convert to CBOR
const auto v = json::to_cbor(j);
CHECK(v == std::vector<std::uint8_t> {0xA1, 0x66, 0x62, 0x69, 0x6E, 0x61, 0x72, 0x79, 0xD8, 0x2A, 0x44, 0xCA, 0xFE, 0xBA, 0xBE});
// parse error when parsing tagged value
CHECK_THROWS_AS(json::from_cbor(v), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(v), "[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: invalid byte: 0xD8");
// binary without subtype when tags are ignored
json jb = json::from_cbor(v, true, true, json::cbor_tag_handler_t::ignore);
CHECK(jb.is_object());
CHECK(jb["binary"].is_binary());
CHECK(!jb["binary"].get_binary().has_subtype());
}
}

View file

@ -278,8 +278,8 @@ TEST_CASE("value conversion")
SECTION("reserve is called on containers that supports it")
{
// make sure all values are properly copied
json j({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
auto v2 = j.get<std::vector<int>>();
json j2({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
auto v2 = j2.get<std::vector<int>>();
CHECK(v2.size() == 10);
}
#endif

View file

@ -37,6 +37,7 @@ using nlohmann::json;
#include <iomanip>
#include <set>
#include <test_data.hpp>
#include <test_utils.hpp>
namespace
{
@ -514,7 +515,7 @@ TEST_CASE("MessagePack")
(static_cast<uint32_t>(result[2]) << 020) +
(static_cast<uint32_t>(result[3]) << 010) +
static_cast<uint32_t>(result[4]);
CHECK(restored == i);
CHECK(static_cast<std::int32_t>(restored) == i);
// roundtrip
CHECK(json::from_msgpack(result) == j);
@ -1609,9 +1610,7 @@ TEST_CASE("single MessagePack roundtrip")
json j1 = json::parse(f_json);
// parse MessagePack file
std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_msgpack)),
std::istreambuf_iterator<char>());
auto packed = utils::read_binary_file(filename + ".msgpack");
json j2;
CHECK_NOTHROW(j2 = json::from_msgpack(packed));
@ -1824,10 +1823,7 @@ TEST_CASE("MessagePack roundtrips" * doctest::skip())
json j1 = json::parse(f_json);
// parse MessagePack file
std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
std::vector<uint8_t> packed(
(std::istreambuf_iterator<char>(f_msgpack)),
std::istreambuf_iterator<char>());
auto packed = utils::read_binary_file(filename + ".msgpack");
json j2;
CHECK_NOTHROW(j2 = json::from_msgpack(packed));
@ -1857,10 +1853,7 @@ TEST_CASE("MessagePack roundtrips" * doctest::skip())
json j1 = json::parse(f_json);
// parse MessagePack file
std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
std::vector<uint8_t> packed(
(std::istreambuf_iterator<char>(f_msgpack)),
std::istreambuf_iterator<char>());
auto packed = utils::read_binary_file(filename + ".msgpack");
json j2;
CHECK_NOTHROW(j2 = json::from_msgpack({packed.data(), packed.size()}));
@ -1875,10 +1868,7 @@ TEST_CASE("MessagePack roundtrips" * doctest::skip())
json j1 = json::parse(f_json);
// parse MessagePack file
std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
std::vector<uint8_t> packed(
(std::istreambuf_iterator<char>(f_msgpack)),
std::istreambuf_iterator<char>());
auto packed = utils::read_binary_file(filename + ".msgpack");
if (!exclude_packed.count(filename))
{

View file

@ -1516,8 +1516,8 @@ TEST_CASE("regression tests")
SECTION("issue #838 - incorrect parse error with binary data in keys")
{
uint8_t key1[] = { 103, 92, 117, 48, 48, 48, 55, 92, 114, 215, 126, 214, 95, 92, 34, 174, 40, 71, 38, 174, 40, 71, 38, 223, 134, 247, 127 };
std::string key1_str(key1, key1 + sizeof(key1) / sizeof(key1[0]));
uint8_t key1[] = { 103, 92, 117, 48, 48, 48, 55, 92, 114, 215, 126, 214, 95, 92, 34, 174, 40, 71, 38, 174, 40, 71, 38, 223, 134, 247, 127, 0 };
std::string key1_str(reinterpret_cast<char*>(key1));
json j = key1_str;
CHECK_THROWS_AS(j.dump(), json::type_error&);
CHECK_THROWS_WITH(j.dump(), "[json.exception.type_error.316] invalid UTF-8 byte at index 10: 0x7E");

View file

@ -36,6 +36,7 @@ using nlohmann::json;
#include <fstream>
#include <set>
#include <test_data.hpp>
#include <test_utils.hpp>
namespace
{
@ -2508,11 +2509,8 @@ TEST_CASE("UBJSON roundtrips" * doctest::skip())
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
// parse MessagePack file
std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary);
std::vector<uint8_t> packed(
(std::istreambuf_iterator<char>(f_ubjson)),
std::istreambuf_iterator<char>());
// parse UBJSON file
auto packed = utils::read_binary_file(filename + ".ubjson");
json j2;
CHECK_NOTHROW(j2 = json::from_ubjson(packed));
@ -2526,7 +2524,7 @@ TEST_CASE("UBJSON roundtrips" * doctest::skip())
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
// parse MessagePack file
// parse UBJSON file
std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary);
json j2;
CHECK_NOTHROW(j2 = json::from_ubjson(f_ubjson));
@ -2541,11 +2539,8 @@ TEST_CASE("UBJSON roundtrips" * doctest::skip())
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
// parse MessagePack file
std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary);
std::vector<uint8_t> packed(
(std::istreambuf_iterator<char>(f_ubjson)),
std::istreambuf_iterator<char>());
// parse UBJSON file
auto packed = utils::read_binary_file(filename + ".ubjson");
json j2;
CHECK_NOTHROW(j2 = json::from_ubjson({packed.data(), packed.size()}));
@ -2559,11 +2554,8 @@ TEST_CASE("UBJSON roundtrips" * doctest::skip())
std::ifstream f_json(filename);
json j1 = json::parse(f_json);
// parse MessagePack file
std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary);
std::vector<uint8_t> packed(
(std::istreambuf_iterator<char>(f_ubjson)),
std::istreambuf_iterator<char>());
// parse UBJSON file
auto packed = utils::read_binary_file(filename + ".ubjson");
{
INFO_WITH_TEMP(filename + ": output adapters: std::vector<uint8_t>");

25
test/utils/test_utils.hpp Normal file
View file

@ -0,0 +1,25 @@
#pragma once
#include <cstdint> // uint8_t
#include <fstream> // ifstream, istreambuf_iterator, ios
#include <vector> // vector
namespace utils
{
inline std::vector<std::uint8_t> read_binary_file(const std::string& filename)
{
std::ifstream file(filename, std::ios::binary);
file.unsetf(std::ios::skipws);
file.seekg(0, std::ios::end);
const auto size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<std::uint8_t> byte_vector;
byte_vector.reserve(static_cast<std::size_t>(size));
byte_vector.insert(byte_vector.begin(), std::istream_iterator<std::uint8_t>(file), std::istream_iterator<std::uint8_t>());
return byte_vector;
}
} // namespace utils