
JSON Link 라이브러리는 다음을 지원하는 할당이 없는 고성능 C++ JSON 라이브러리입니다.
라이브러리는 혼합할 수 있는 다른 구문 분석 모드도 지원합니다.
json_array_iterator 또는 json_array_range 유형을 사용할 수 있습니다.json_value 유형다른 주목할만한 기능은 다음과 같습니다.
boost::multiprecision::cpp_int 또는 GNU BigNum/Rational mpq_t 와 같은 다른 숫자 유형과 구문 분석할 수 있습니다.도서관은 BSL 라이센스를 사용하고 있습니다
JSON 문서의 구조를 알면 구문 분석은 다음과 같습니다.
MyThing thing = daw::json::from_json<MyThing>( json_string );또는 문서의 루트가 배열인 배열 문서의 경우 이를 더 쉽게 만드는 도우미 메서드가 있으며 다음과 같이 구문 분석할 수 있습니다.
std::vector<MyThing> things = daw::json::from_json_array<MyThing>( json_string2 ); JSON 문서의 구조를 알 수 없는 경우 뷰 역할을 하고 요청 시 반복 및 풀 구문 분석을 허용하는 json_value 를 생성할 수 있습니다. 다음은 JSON 데이터에서 json_value 여는 예입니다.
json_value val = daw::json::json_value( json_string ); from_json 및 to_json 메서드를 사용하면 대부분의 구문 분석 및 직렬화 요구 사항에 액세스할 수 있습니다.
이벤트 기반 파서(SAX)는 daw::json::json_event_parser 통해 호출할 수 있습니다. json 문서와 이벤트 핸들러라는 두 개의 인수가 필요합니다. 이벤트 핸들러는 다음 멤버 중 하나를 사용하여 이벤트를 선택할 수 있습니다.
클래스를 JSON 문서에 매핑하는 작업은 daw::json::json_data_contract 특성을 특수화하여 수행됩니다. 매핑된 클래스는 매핑된 다른 클래스의 멤버인 경우 다시 매핑할 필요가 없습니다. json_data_contract 특성에는 두 부분이 있습니다. 첫 번째는 JSON 멤버를 클래스 생성자에 매핑하는 type 이라는 유형 별칭입니다. 이는 직렬화할 데이터가 클래스를 구성하는 데에도 필요하다고 가정하여 클래스에 대한 비공개 액세스가 필요한 문제를 해결합니다. 예를 들어:
struct Thing {
int a;
int b;
}; Thing 의 구성에는 2개의 정수가 필요하며 다음 JSON이 있는 경우:
{
"a" : 42 ,
"b" : 1234
}다음과 같이 매핑을 수행할 수 있습니다.
namespace daw ::json {
template <>
struct json_data_contract <Thing> {
static constexpr char const a[] = " a " ;
static constexpr char const b[] = " b " ;
using type = json_member_list<
json_number<a, int >,
json_number<b, int >
>;
};
} 이는 문서의 JSON 클래스에 정수인 숫자인 "a"와 "b"라는 두 개 이상의 멤버가 있음을 의미합니다. Thing daw::json::from_json<Thing>( json_doc ); 호출되거나 다른 클래스에 json_class<MemberName, Thing> 멤버 매핑이 있습니다. 위의 내용은 이름에 대한 C++17 매핑 방법이며 향후 C++ 버전에서도 작동합니다. 그러나 C++20 이상에서는 이름이 매핑에 인라인으로 포함될 수 있습니다(예: json_number<"a", int> . 위의 내용은 JSON을 구문 분석하는 데 필요한 전부이며, 특성에 정적 멤버 함수를 직렬화하는 데 필요합니다. 이전 예제를 사용하여 확장하면 다음과 같이 Thing 직렬화할 수 있습니다.
namespace daw ::json {
template <>
struct json_data_contract <Thing> {
static constexpr char const a[] = " a " ;
static constexpr char const b[] = " b " ;
using type = json_member_list<
json_number<a, int >,
json_number<b, int >
>;
};
static auto to_json_data ( Thing const & v ) {
return std::forward_as_tuple ( v. a , v. b );
}
} 튜플로 반환된 멤버의 순서는 type 별칭 type 의 매핑과 일치해야 합니다. 이를 통해 데이터 멤버가 공개되지 않은 경우 접근자 메서드의 결과도 전달할 수 있습니다. 또한 Thing 클래스는 int, int 에서 구성 가능해야 합니다. 라이브러리는 C++17에서 일반 생성자와 집계 init( Thing{ int, int } 및 Thing( int, int ) )를 모두 지원합니다.
to_json_data 의 반환 유형은 기존 객체 멤버에 대한 참조 튜플을 반환할 필요는 없지만 계산된 값도 반환할 수 있습니다. rvalue는 일시적인 경우가 많으므로 rvalue를 허용하지 않으며 장거리 디버깅이 발생할 수 있습니다. 라이브러리는 이에 대해 static_assert하고 <daw/daw_tuple_forward.h> 포함하고 임시를 저장하고 다른 참조 유형을 전달하는 daw::forward_nonrvalue_as_tuple( ... ) 호출할 것을 제안합니다. 파서는 클래스 생성자 호출 시 각 인수를 구성하여 작동합니다. 개별 인수 파서는 데이터의 지정된 상황(예: 부동 소수점 및 정수)에 맞게 조정될 수 있습니다. 그런 다음 C++ 클래스를 구성하는 데 필요한 인수와 해당 순서를 정의하는 유형 특성을 사용하여 JSON의 각 멤버를 볼 수 있습니다. 이제 각 파서의 결과로 값을 구성합니다. T{ parse<0, json_string<"name">>( data ), parse<1, json_number<"age", unsigned>>( data ), parse<json_number<2, "number>>( data )} 와 유사 각 멤버에 대해 데이터 스트림은 구문 분석해야 하는 멤버를 찾을 때까지 앞으로 이동하여 나중에 구문 분석을 위해 관심 있는 위치를 저장합니다. json_class<"member_name", Type> 매핑 유형입니다. 따라서 각 매핑 특성은 세부 정보가 아닌 특정 멤버만 처리해야 합니다. 
이름이 지정되지 않은 컨텍스트(예: 루트 값, 배열 요소, 일부 키 값 유형 및 이름이 no_name 인 변형 요소 목록)에서는 JSON 매핑 유형 대신 일부 기본 C++ 데이터 유형을 사용할 수 있습니다. 여기에는 정수, 부동 소수점, bool, std::string, std::string_view, 연관 컨테이너, 시퀀스 컨테이너, Nullable/Optional 유사 유형 및 이전에 매핑된 클래스가 포함됩니다.
예를 들어, 문자열 배열을 매핑합니다.
template <>
struct daw ::json::json_data_contract<MyType> {
using type = json_member_list<json_array< " member_name " , std::string>>;
}; vcpkg를 사용하여 최신 릴리스를 가져올 수 있으며 포트 이름은 daw-json-link 입니다.
find_package ( daw-json-link )
#...
target_link_libraries ( MyTarget daw::daw-json-link ) 라이브러리는 헤더일 뿐이며 두 가지 종속성과 함께 복제할 수 있으며 각 폴더의 include/ 하위 폴더를 컴파일러의 포함 경로에 추가할 수 있습니다.
cmake 프로젝트에서 daw_json_link를 사용하려면 다음을 추가하면 종속성과 함께 가져올 수 있습니다.
include ( FetchContent )
FetchContent_Declare(
daw_json_link
GIT_REPOSITORY https://github.com/beached/daw_json_link
GIT_TAG release
)
FetchContent_MakeAvailable(daw_json_link)
#...
target_link_libraries ( MyTarget daw::daw-json-link )Bash가 있는 시스템에서는 다른 시스템에서도 비슷합니다. 시스템에 다음을 설치할 수 있습니다.
git clone https://github.com/beached/daw_json_link
cd daw_json_link
mkdir build
cd build
cmake ..
cmake --install . 이렇게 하면 cmake find_package 설치가 허용되거나 설치 접두사의 포함 폴더가 컴파일러의 포함 경로에 포함되어 있는 한 이를 일반 헤더로 사용할 수 있습니다.
다음은 테스트를 빌드하고 실행합니다.
git clone https://github.com/beached/daw_json_link
cd daw_json_link
mkdir build
cd build
cmake -DDAW_ENABLE_TESTING=On ..
cmake --build .
ctest . 빌드 후에는 개별 예제도 테스트할 수 있습니다. city_test_bin 도시 JSON 파일의 경로가 필요합니다.
./tests/city_test_bin ../test_data/cities.json가능하다면 데이터 구조의 멤버 순서는 일반적으로 JSON 데이터의 순서와 일치해야 합니다. 값을 역추적할 필요가 없으면 파서가 더 빠릅니다. JSON 데이터에 선택적 값이 누락된 경우 구문 분석 속도가 느려질 수도 있습니다. 가능하다면 null로 보내십시오. 파서는 할당하지 않습니다. 데이터 유형으로 구문 분석하면 데이터 구조가 할당을 수행하므로 사용자 정의 할당자 또는 혼합을 사용할 수 있습니다. 배열의 기본값은 std::Vector를 사용하는 것이며 이것이 바람직하지 않은 경우 유형을 제공해야 합니다.

현재 라이브러리는 직렬화 시 멤버 이름을 이스케이프/이스케이프 처리하지 않으며 유효하고 이스케이프가 불가능한 것으로 예상됩니다. 비용이 들기 때문에 향후 선택적으로 추가할 수 있습니다.
C++17과 C++20 사이에는 약간의 차이가 있습니다. 여기서 C++20은 C++17에서 사용할 수 없는 일부 코드를 허용합니다.
namespace daw ::json {
template <>
struct json_data_contract <MyType> {
static constexpr char const member_name[] = " memberName " ;
using type = json_member_list<json_number<member_name>>;
};
}C++의 두 버전 모두 멤버 이름 지정을 위해 이 방법을 지원합니다.
C++20 컴파일러 내에서 컴파일할 때 C++17에서처럼 char const * 전달하는 것 외에도 멤버 이름을 문자열 리터럴로 직접 지정할 수 있습니다. C++20 컴파일러 지원은 아직 초기 단계이며 여기에 용이합니다. C++20 모드의 g++9.x에는 알려진 문제가 있으며 g++10/11에서만 테스트되었습니다. 여기 용들이 있네
namespace daw ::json {
template <>
struct json_data_contract <MyType> {
using type = json_member_list<json_number< " member_name " >>;
};
} 데이터 유형이 json_data_contract 로 매핑되면 라이브러리는 JSON을 구문 분석하는 메서드를 제공합니다.
MyClass my_class = from_json<MyClass>( json_str );또는 입력을 신뢰할 수 있는 경우 덜 확인된 버전이 더 빠를 수 있습니다.
MyClass my_class = from_json<MyClass, options::parse_flags<options::CheckedParseMode::no>>( json_str ); 배열 루트가 있는 JSON 문서는 from_json_array 함수를 사용하여 구문 분석합니다.
std::vector<MyClass> my_data = from_json_array<MyClass>( json_str );또는 입력을 신뢰할 수 있는 경우 덜 확인된 버전이 더 빠를 수 있습니다.
std::vector<MyClass> my_data = from_json_array<MyClass, std::vector<MyClass>, options::parse_flags<options::CheckedParseMode::no>>( json_str );json_array_iterator JSON 배열 데이터에서 작업하려면 반복자를 가져오고 std 알고리즘을 사용하여 JSON 데이터의 배열을 반복하는 작업은 json_array_iterator 통해 수행할 수 있습니다.
using iterator_t = json_array_iterator<MyClass>;
auto pos = std::find( iterator_t ( json_str ), iterator_t ( ), MyClass( ... ) );또는 입력을 신뢰할 수 있는 경우 덜 확인된 버전을 호출할 수 있습니다.
using iterator_t = daw::json::json_array_iterator<MyClass, options::CheckedParseMode::no>;
auto pos = std::find( iterator_t ( json_str ), iterator_t ( ), MyClass( ... ) );json_value API와 같은 DOM의 경우 GUI와 같은 용도로 자주 사용되며 매핑이 부적절할 때 코드를 제공하는 경우 json_value 사용할 수 있습니다. 이는 json_to_cpp 도구에서 사용됩니다.
auto jv = daw::json::json_value( json_doc );JSON 경로를 사용하여 정수를 추출할 수 있습니다.
int foo = as< int >( jv[ " path.to.int " ] ); 여기서 "path.to.int" 다음과 같은 JSON 클래스로의 드릴링을 나타내는 JSON 경로입니다.
{
"path" : {
"to" : {
"int" : 5
}
}
} 또한 JSON 경로의 구문과 같은 배열을 통해 선택할 수도 있습니다. "path[5]" 는 "path" 의 5번째 요소/멤버를 선택합니다. JSON으로 직렬화하려는 경우. JSON 경로 구문은 from_json , from_json_array 및 json_array_iterator 에서도 작동합니다.
to_jsonstd::string my_json_data = to_json( MyClass{} ); 또는 사물의 배열, 컬렉션, 범위 또는 보기를 직렬화합니다. 해당 유형에 대해 작동하려면 std::begin(...) 및 std::end(...) 만 필요합니다. 이를 통해 유형이 구성 가능한 항목 모음이 아닌 경우 직렬화가 가능합니다.
std::vector<MyClass> arry = ...;
std::string my_json_data = to_json_array( arry ); 구문 분석 오류는 기본적으로 실패 이유 및 위치에 대한 정보가 포함된 daw::json::json_exception 발생시킵니다.
예외가 비활성화되면 라이브러리는 기본적으로 구문 분석 오류 시 std::terminate 호출합니다.
반면 오류 처리는 기본적으로 오류 시 daw::json::json_exception 발생시키거나 예외가 비활성화된 경우 std::terminate 호출하는 것으로 설정됩니다. 함수 포인터 daw::json::daw_json_error_handler 설정하여 이 동작을 변경할 수 있습니다. 유일한 요구 사항은 함수가 반환되지 않는다는 것입니다. 이를 활용하는 예는 error_handling_bench_test.cpp에 있습니다.
오류 검사는 구문 분석별로 수정할 수 있습니다. from_json , from_json_array , json_value , json_array_iterator 등은 모두 구문 분석 옵션을 지원합니다. 호출에는 파서 옵션이 제공될 수 있습니다. 사용 가능한 옵션은 parser_policies 쿡북 항목에 문서화되어 있습니다.
daw::json::json_exception 에는 std::string_view reason( ) const 멤버 함수가 std::exception 의 what( ) 과 유사하지만 what( ) 보다 더 많은 컨텍스트가 포함된 std::string 반환합니다. 예외가 있는 환경에서 예외를 비활성화하려면 DAW_JSON_DONT_USE_EXCEPTIONS 정의하여 라이브러리에서 발생하는 예외를 비활성화하거나 핸들러를 설정할 수 있습니다. 핸들러는 두 가지 기본값 daw::json::default_error_handling_throwing 중 하나로 설정될 수 있으므로 더 이상 권장되지 않습니다. daw::json::default_error_handling_throwing 또는 daw::json::default_error_handling_terminating .
이는 daw::json 네임스페이스에 json_data_contract 의 특수화를 작성하여 수행할 수 있습니다. 예를 들어:
# include < daw/json/daw_json_link.h >
# include < string >
# include < string_view >
# include < vector >
struct TestClass {
int i = 0 ;
double d = 0.0 ;
bool b = false ;
std::string s{};
std::vector< int > y{};
TestClass ( int Int, double Double, bool Bool, std::string S,
std::vector< int > Y)
: i(Int), d(Double), b(Bool), s(std::move( S ) ), y(std::move( Y )) {}
};
namespace daw ::json {
template <>
struct json_data_contract <TestClass> {
using type =
json_member_list<
json_number< " i " , int >,
json_number< " d " >,
json_bool< " b " >,
json_string< " s " >,
json_array< " y " , int >
>;
};
} // namespace daw::json
int main () {
std::string_view test_001_t_json_data = R"( {
"i":5,
"d":2.2e4,
"b":false,
"s":"hello world",
"y":[1,2,3,4]
} )" ;
std::string_view json_array_data = R"( [{
"i":5,
"d":2.2e4,
"b":false,
"s":"hello world",
"y":[1,2,3,4]
},{
"i":4,
"d":122e4,
"b":true,
"s":"goodbye world",
"y":[4,3,1,4]
}] )" ;
TestClass test_class = daw::json::from_json<TestClass>(test_001_t_json_data);
std::vector<TestClass> arry_of_test_class =
daw::json::from_json_array<TestClass>(test_001_t_json_data);
}컴파일러 탐색기 참조
집계 생성자와 사용자 생성자가 모두 지원됩니다. 설명은 유형과 순서를 구성하는 데 필요한 값을 제공합니다. 지정된 순서는 생성자에 배치되는 순서입니다. 유형을 구성하는 방법을 제공하는 사용자 정의 지점도 있습니다. 다음과 같은 수업:
# include < daw/json/daw_json_link.h >
struct AggClass {
int a{};
double b{};
};
namespace daw ::json {
template <>
struct json_data_contract <AggClass> {
using type = json_member_list<
json_number< " a " , int >,
json_number< " b " >
>;
};
}작동합니다. 동일하지만 C++17
# include < daw/json/daw_json_link.h >
struct AggClass {
int a{};
double b{};
};
namespace daw ::json {
template <>
struct json_data_contract <AggClass> {
static inline constexpr char const a[] = " a " ;
static inline constexpr char const b[] = " b " ;
using type = json_member_list<
json_number<a, int >,
json_number<b>
>;
};
} 클래스 설명은 해당 하위 멤버와 함께 재귀적입니다. 이전 AggClass 사용하면 이를 다른 클래스의 멤버로 포함할 수 있습니다.
// See above for AggClass
struct MyClass {
AggClass other;
std::string_view some_name;
};
namespace daw ::json {
template <>
struct json_data_contract <MyClass> {
using type = json_member_list<
json_class< " other " , AggClass>,
json_string< " id " , std::string_view>
>;
};
} 위의 내용은 AggClass로 설명된 다른 클래스가 있는 MyClass 클래스를 매핑합니다. 또한 C++ 클래스의 멤버 이름은 매핑된 JSON 이름의 멤버 이름과 일치할 필요가 없으며 문자열은 std::string_view 결과 유형으로 사용할 수 있다는 것을 알 수 있습니다. 클래스가 존재하는 한 JSON 파일이 포함된 버퍼가 존재한다는 것을 보장할 수 있다면 이는 중요한 성능 향상입니다.
JSON 배열을 반복합니다. 입력 반복기 daw::json::json_array_iterator<JsonElement> 사용하면 JSON 요소 배열을 반복할 수 있습니다. 기술적으로는 입력 반복자이지만 정방향 반복자처럼 저장하고 재사용할 수 있습니다. 참조가 아니라 값을 반환합니다.
# include < daw/json/daw_json_link.h >
# include < daw/json/daw_json_iterator.h >
# include < iostream >
struct AggClass {
int a{};
double b{};
};
namespace daw ::json {
template <>
struct json_data_contract <AggClass> {
using type = json_member_list<
json_number< " a " , int >,
json_number< " b " >
>;
};
} // namespace daw::json
int main () {
std::string json_array_data = R"( [
{"a":5,"b":2.2},
{"a":5,"b":3.14},
{"a":5,"b":0.122e44},
{"a":5334,"b":34342.2}
] )" ;
using iterator_t = daw::json::json_array_iterator<AggClass>;
auto pos =
std::find_if (
iterator_t (json_array_data),
iterator_t (),
[](AggClass const &element) {
return element. b > 1000.0 ;
}
);
if (pos == iterator_t ()) {
std::cout << " Not found n " ;
} else {
std::cout << " Found n " ;
}
} 구문 분석은 특정 멤버나 요소에서 시작할 수 있습니다. from_json , from_json_array , json_value , json_array_iterator 등에 대한 선택적 멤버 경로를 지정할 수 있습니다. 형식은 점으로 구분된 멤버 이름 목록이며 선택적으로 member0.member1 과 같은 배열 인덱스입니다. 이는 다음과 같은 구문 분석과 같습니다.
{
"member0" : {
"member1" : {}
}
} 또는 다음과 같이 문서의 "member1"에서 구문 분석을 시작하는 member0[5].member1 입니다.
{
"member0" : [
" a " ,
" b " ,
" c " ,
" d " ,
" e " ,
{
"member1" : " "
}
]
}또는
{
"member0" : {
"a" : " " ,
"b" : " " ,
"c" : " " ,
"d" : " " ,
"e" : " " ,
"f" : {
"member1" : " "
}
}
}주석에 대한 파서 정책이 사용될 때 주석이 지원됩니다. 현재 댓글 정책에는 두 가지 형태가 있습니다.
// 줄 주석 및 C 스타일 /* */ 주석. { // This is a comment
"a" /*this is also a comment*/: "a's value"
}
# 줄 주석 { # This is a comment
"a" #this is also a comment
: "a's value"
}
댓글 정책은 PolicyCommentTypes 통해 설정할 수 있습니다. 자세한 내용은 parser_policies를 참조하세요.
직렬화를 활성화하려면 json_data_contract 전문화에 to_json_data( Thing const & ); 이는 멤버의 튜플을 반환합니다. 이는 클래스 설명에 제공된 인수에 대한 유형의 매핑을 제공합니다. JSON 문자열로 직렬화하려면 다음을 호출합니다 to_json( my_thing ); 여기서 my_thing 은 등록된 유형이거나 컨테이너, 맵, 문자열, 부울 및 숫자와 같은 기본 유형 중 하나입니다. to_json_data( Thing const & ) 정적 메서드의 결과는 함께 제공되는 json_data_contract 유형 별칭 type 의 요소가 순서와 일치하는 tuple 입니다. 메서드가 사용되는 방식으로 인해 rvalue 요소가 있는 튜플은 파괴 후 사용 버그가 발생합니다. 이런 일이 발생하면 컴파일러에서 오류가 발생합니다. 대신 <daw/daw_tuple_forward.h> 및 daw::forward_nonrvalue_as_tuple 메서드를 포함하면 rvalue를 참조로 전달하는 대신 저장합니다. 종종 이는 계산된 튜플 요소의 결과입니다. 위의 예를 사용하여 to_json_data 메소드를 추가할 수 있습니다.
# include < daw/json/daw_json_link.h >
# include < tuple >
struct AggClass {
int a;
double b;
};
namespace daw ::json {
template <>
struct json_data_contract <AggClass> {
using type = json_member_list<
json_number< " a " , int >,
json_number< " b " >
>;
static constexpr auto to_json_data ( AggClass const & value ) {
return std::forward_as_tuple ( value. a , value. b );
}
};
}
// ...
AggData value = // ...;
std::string test_001_t_json_data = to_json( value );
// or
std::vector<AggData> values = // ...;
std::string json_array_data = to_json_array( values ); 또는 WritableOutput 유형으로 출력할 수 있습니다. 기본적으로 여기에는 FILE*, iostream, 문자 컨테이너 및 문자 포인터가 포함됩니다. 귀하의 유형의 json_data_constract 에서. 또는 선택한 경우 opt_into_iostreams 라는 유형 별칭을 추가하여 json을 출력 스트림에 삽입하는 유형에 대해 ostream 연산자<<를 얻을 수 있습니다. 별칭 유형은 중요하지 않으며 daw/json/daw_json_iostream.h 포함합니다. . 예를 들어
# include < daw/json/daw_json_link.h >
# include < daw/json/daw_json_iostream.h >
# include < tuple >
struct AggClass {
int a{};
double b{};
};
namespace daw ::json {
template <>
struct json_data_contract <AggClass> {
using opt_into_iostreams = void ;
using type = json_member_list<
json_number< " a " , int >,
json_number< " b " >
>;
static inline auto to_json_data ( AggClass const & value ) {
return std::forward_as_tuple ( value. a , value. b );
}
};
}
// ...
AggData value = // ...;
std::cout << value << ' n ' ;
// or
std::vector<AggData> values = // ...;
std::cout << values << ' n ' ;실제 예제는 daw_json_iostream_test.cpp 또는 컴파일러 탐색기에서 찾을 수 있습니다.
error: pointer to subobject of string literal is not allowed in a template argument constexpr char const member_name[] = " member_name " ;
// ...
json_link<member_name, Type>JSON Link 작동 방식에 영향을 미치는 몇 가지 정의가 있습니다.
DAW_JSON_DONT_USE_EXCEPTIONS - 예외 허용 여부를 제어합니다. 그렇지 않은 경우 오류 시 std::terminate() 발생합니다. 예외가 비활성화된 경우 자동으로 수행됩니다(예: -fno-exceptions ).DAW_ALLOW_SSE42 - 실험적인 SSE42 모드를 허용합니다. 일반적으로 constexpr 모드가 더 빠릅니다.DAW_JSON_NO_CONST_EXPR - 이동/복사 특수 멤버가 없는 클래스가 C++ 20 이전의 JSON 데이터에서 구성되도록 허용하는 데 사용할 수 있습니다. 이 모드는 이 플래그가 더 이상 필요하지 않은 경우 C++20 이전의 상수 표현식에서는 작동하지 않습니다. 이전 컴파일러는 여전히 작동할 수 있지만 일부 테스트에서는 버그가 있는 C++17 지원으로 인해 ICE 또는 컴파일 오류가 발생했습니다. 종종 constexpr을 사용하지 않는 것도 도움이 될 수 있습니다.
json_key_value 구문 분석 유형을 사용하면 둘 다 구문 분석하거나 주문할 수 있음을 보장할 수 있습니다.std::multimap<std::string, T> 또는 std::vector<std::pair<std::string, T>> 와 함께 사용하면 모든 멤버가 전자와 함께 순서대로 유지됩니다. 또는 json_value 유형을 사용하면 클래스 멤버에 대한 반복과 올바른 멤버의 지연 구문 분석이 가능합니다. 이러한 방법을 보여주는 요리책 키 값을 참조하세요.