세계에서 가장 빠른 JSON 라이브러리 중 하나입니다. Glaze는 객체 메모리에서 읽고 쓰며 인터페이스를 단순화하고 놀라운 성능을 제공합니다.
Glaze는 다음도 지원합니다:
구조체에 대한 순수 컴파일 시간 반영
UTF-8 검증을 통한 JSON RFC 8259 준수
표준 C++ 라이브러리 지원
헤더만
메모리 직렬화/역직렬화에 직접 연결
지속적인 시간 조회와 완벽한 해싱으로 시간 맵 컴파일
읽기/쓰기 동작을 수정하는 강력한 래퍼(래퍼)
사용자 정의 읽기/쓰기 기능 사용(Custom Read/Write)
빠르고 유연한 방식으로 알 수 없는 키를 처리합니다.
JSON 포인터 구문을 통한 직접 메모리 액세스
최대 성능을 위해 동일한 API를 통한 바이너리 데이터
예외 없음( -fno-exceptions
로 컴파일)
런타임 유형 정보가 필요하지 않습니다( -fno-rtti
로 컴파일).
단락을 통한 신속한 오류 처리
JSON-RPC 2.0 지원
JSON 스키마 생성
휴대성이 매우 뛰어나고 폭넓은 호환성을 위해 세심하게 최적화된 SWAR(SIMD Within A Register)을 사용합니다.
부분 읽기 및 부분 쓰기 지원
CSV 읽기/쓰기
훨씬 더!
자세한 문서는 DOCS를 참조하세요.
도서관 | 왕복 시간(초) | 쓰기(MB/초) | 읽기(MB/초) |
---|---|---|---|
잿물 | 1.04 | 1366 | 1224 |
simdjson(요청 시) | 해당 없음 | 해당 없음 | 1198 |
yyjson | 1.23 | 1005 | 1107 |
daw_json_link | 2.93 | 365 | 553 |
RapidJSON | 3.65 | 290 | 450 |
Boost.JSON(직접) | 4.76 | 199 | 447 |
json_struct | 5.50 | 182 | 326 |
눌만 | 15.71 | 84 | 80 |
여기에서 사용 가능한 성능 테스트 코드
성능 주의 사항: simdjson 및 yyjson은 훌륭하지만 데이터가 예상 순서에 있지 않거나 키가 누락된 경우 심각한 성능 손실을 경험합니다(문서를 반복해야 하기 때문에 파일 크기가 커짐에 따라 문제가 커집니다).
또한 simdjson 및 yyjson은 자동 이스케이프 문자열 처리를 지원하지 않으므로 이 벤치마크에서 현재 이스케이프되지 않은 문자열 중 하나에 이스케이프가 포함되어 있으면 이스케이프가 처리되지 않습니다.
ABC 테스트는 키가 예상 순서에 있지 않을 때 simdjson의 성능이 어떻게 저하되는지 보여줍니다.
도서관 | 읽기(MB/초) |
---|---|
잿물 | 678 |
simdjson(요청 시) | 93 |
태그된 바이너리 사양: BEVE
미터법 | 왕복 시간(초) | 쓰기(MB/초) | 읽기(MB/초) |
---|---|---|---|
원시 성능 | 0.42 | 3235 | 2468 |
동등한 JSON 데이터* | 0.42 | 3547 | 2706 |
JSON 크기: 670바이트
BEVE 크기: 611바이트
*BEVE는 JSON보다 더 효율적으로 압축하므로 동일한 데이터를 훨씬 더 빠르게 전송할 수 있습니다.
구조체가 자동으로 반영됩니다! 사용자에게는 메타데이터가 필요하지 않습니다.
struct my_struct
{
int i = 287 ;
double d = 3.14 ;
std::string hello = " Hello World " ;
std::array< uint64_t , 3 > arr = { 1 , 2 , 3 };
std::map<std::string, int > map{{ " one " , 1 }, { " two " , 2 }};
};
JSON (정화된)
{
"i" : 287 ,
"d" : 3.14 ,
"hello" : " Hello World " ,
"arr" : [
1 ,
2 ,
3
],
"map" : {
"one" : 1 ,
"two" : 2
}
}
JSON 작성
my_struct s{};
std::string buffer = glz::write_json(s).value_or( " error " );
또는
my_struct s{};
std::string buffer{};
auto ec = glz::write_json(s, buffer);
if (ec) {
// handle error
}
JSON 읽기
std::string buffer = R"( {"i":287,"d":3.14,"hello":"Hello World","arr":[1,2,3],"map":{"one":1,"two":2}} )" ;
auto s = glz::read_json<my_struct>(buffer);
if (s) // check std::expected
{
s. value (); // s.value() is a my_struct populated from buffer
}
또는
std::string buffer = R"( {"i":287,"d":3.14,"hello":"Hello World","arr":[1,2,3],"map":{"one":1,"two":2}} )" ;
my_struct s{};
auto ec = glz::read_json(s, buffer); // populates s from buffer
if (ec) {
// handle error
}
auto ec = glz::read_file_json(obj, " ./obj.json " , std::string{});
auto ec = glz::write_file_json(obj, " ./obj.json " , std::string{});
중요한
파일 이름(두 번째 인수)은 null로 끝나야 합니다.
Apple, Windows 및 Linux에서 Clang(17+), MSVC(2022) 및 GCC(12+)를 사용하여 작업을 빌드하고 테스트합니다.
Glaze는 최신 세 가지 버전의 GCC 및 Clang뿐만 아니라 최신 버전의 MSVC 및 Apple Clang과의 호환성을 유지하려고 합니다.
Glaze에는 C++ 표준을 준수하는 전처리기가 필요하며, 이는 MSVC로 빌드할 때 /Zc:preprocessor
플래그가 필요합니다.
CMake에는 glaze_ENABLE_AVX2
옵션이 있습니다. 구성 중인 시스템이 이를 지원하는 한 성능을 향상시키기 위해 경우에 따라 AVX2
SIMD 지침을 사용하려고 시도합니다. Arm용으로 크로스 컴파일하는 경우와 같이 AVX2 명령어 세트를 비활성화하려면 이 옵션을 OFF
로 설정합니다. CMake를 사용하지 않는 경우 매크로 GLZ_USE_AVX2
가 정의된 경우 기능을 활성화합니다.
include (FetchContent)
FetchContent_Declare(
glaze
GIT_REPOSITORY https://github.com/stephenberry/glaze.git
GIT_TAG main
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(glaze)
target_link_libraries ( ${PROJECT_NAME} PRIVATE glaze::glaze)
find_package(glaze REQUIRED)
target_link_libraries(main PRIVATE glaze::glaze)
import libs = libglaze%lib{glaze}
반사를 전문화하려면 선택적으로 아래 코드를 작성할 수 있습니다.
이 메타데이터는 집계되지 않은 초기화 가능 구조체에도 필요합니다.
template <>
struct glz ::meta<my_struct> {
using T = my_struct;
static constexpr auto value = object(
&T::i,
&T::d,
&T::hello,
&T::arr,
&T::map
);
};
struct my_struct
{
int i = 287 ;
double d = 3.14 ;
std::string hello = " Hello World " ;
std::array< uint64_t , 3 > arr = { 1 , 2 , 3 };
std::map<std::string, int > map{{ " one " , 1 }, { " two " , 2 }};
struct glaze {
using T = my_struct;
static constexpr auto value = glz::object(
&T::i,
&T::d,
&T::hello,
&T::arr,
&T::map
);
};
};
Glaze 메타데이터를 정의하면 객체는 멤버 객체 포인터의 비정적 이름을 자동으로 반영합니다. 그러나 사용자 지정 이름을 원하거나 필드 이름을 제공하지 않는 람다 함수 또는 래퍼를 등록하는 경우 선택적으로 메타데이터에 필드 이름을 추가할 수 있습니다.
사용자 정의 이름의 예:
template <>
struct glz ::meta<my_struct> {
using T = my_struct;
static constexpr auto value = object(
" integer " , &T::i,
" double " , &T::d,
" string " , &T::hello,
" array " , &T::arr,
" my map " , &T::map
);
};
이러한 각 문자열은 선택 사항이며 이름을 반영하려는 경우 개별 필드에서 제거할 수 있습니다.
이름은 다음 항목에 필요합니다.
- 정적 constexpr 멤버 변수
- 래퍼
- 람다 함수
Glaze는 glz::meta
특수화를 통해 수정할 수 있는 컴파일 시간 반영 API를 제공합니다. 이 리플렉션 API는 glz::meta
특수화가 제공되지 않는 한 순수 리플렉션을 사용합니다. 이 경우 개발자가 기본 동작을 재정의합니다.
static_assert (glz::reflect<my_struct>::size == 5 ); // Number of fields
static_assert (glz::reflect<my_struct>::keys[ 0 ] == " i " ); // Access keys
경고
위에 설명된 glz::reflect
필드는 공식화되었으며 변경될 가능성이 없습니다. glz::reflect
구조체 내의 다른 필드는 사양을 계속 공식화함에 따라 발전할 수 있습니다. 따라서 향후 문서화되지 않은 필드에 대한 주요 변경 사항이 발생할 수 있습니다.
맞춤형 읽기 및 쓰기는 여기에 설명된 강력한 to
/ from
전문화 접근 방식을 통해 달성할 수 있습니다: custom-serialization.md. 그러나 이는 사용자 정의 유형에만 작동합니다.
일반적인 사용 사례나 특정 멤버 변수에 특별한 읽기 및 쓰기가 필요한 경우에는 glz::custom
사용하여 읽기/쓰기 멤버 함수, std::functions 또는 람다 함수를 등록할 수 있습니다.
struct custom_encoding
{
uint64_t x{};
std::string y{};
std::array< uint32_t , 3 > z{};
void read_x ( const std::string& s) {
x = std::stoi (s);
}
uint64_t write_x () {
return x;
}
void read_y ( const std::string& s) {
y = " hello " + s;
}
auto & write_z () {
z[ 0 ] = 5 ;
return z;
}
};
template <>
struct glz ::meta<custom_encoding>
{
using T = custom_encoding;
static constexpr auto value = object( " x " , custom<&T::read_x, &T::write_x>, //
" y " , custom<&T::read_y, &T::y>, //
" z " , custom<&T::z, &T::write_z>);
};
suite custom_encoding_test = [] {
" custom_reading " _test = [] {
custom_encoding obj{};
std::string s = R"( {"x":"3","y":"world","z":[1,2,3]} )" ;
expect (! glz::read_json (obj, s));
expect (obj. x == 3 );
expect (obj. y == " helloworld " );
expect (obj. z == std::array< uint32_t , 3 >{ 1 , 2 , 3 });
};
" custom_writing " _test = [] {
custom_encoding obj{};
std::string s = R"( {"x":"3","y":"world","z":[1,2,3]} )" ;
expect (! glz::read_json (obj, s));
std::string out{};
expect ( not glz::write_json (obj, out));
expect (out == R"( {"x":3,"y":"helloworld","z":[5,2,3]} )" );
};
};
멤버 포인터(예 &T::a
)를 사용할 때 C++ 클래스 구조는 JSON 인터페이스와 일치해야 합니다. 레이아웃이 다른 C++ 클래스를 동일한 개체 인터페이스에 매핑하는 것이 바람직할 수 있습니다. 이는 멤버 포인터 대신 람다 함수를 등록하여 수행됩니다.
template <>
struct glz ::meta<Thing> {
static constexpr auto value = object(
" i " , []( auto && self) -> auto & { return self. subclass . i ; }
);
};
람다 함수에 전달된 self
값은 Thing
개체가 되며, 람다 함수를 사용하면 하위 클래스를 개체 인터페이스에 보이지 않게 만들 수 있습니다.
Lambda 함수는 기본적으로 복사 반환을 수행하므로 Glaze가 메모리에 쓰려면 일반적으로 auto&
반환 유형이 필요합니다.
글레이즈는 쓰기/읽기 시 동일한 방식으로 값, 포인터 및 참조를 처리하므로 포인터/참조를 통해서도 리매핑을 수행할 수 있습니다.
클래스는 다음과 같이 기본 값으로 처리될 수 있습니다.
struct S {
int x{};
};
template <>
struct glz ::meta<S> {
static constexpr auto value{ &S::x };
};
또는 람다를 사용하여:
template <>
struct glz ::meta<S> {
static constexpr auto value = []( auto & self) -> auto & { return self. x ; };
};
Glaze는 신뢰할 수 없는 메시지에 사용해도 안전합니다. 오류는 일반적으로 std::expected
glz::expected
내에서 오류 코드로 반환됩니다.
Glaze는 단락 오류 처리에 작동합니다. 이는 오류가 발생하면 구문 분석이 매우 빠르게 종료됨을 의미합니다.
더 유용한 오류 메시지를 생성하려면 format_error
호출하세요.
auto pe = glz::read_json(obj, buffer);
if (pe) {
std::string descriptive_error = glz::format_error (pe, buffer);
}
이 테스트 사례는 다음과 같습니다.
{ "Hello" : " World " x, "color": "red" }
다음 오류가 발생합니다.
1:17: expected_comma
{"Hello":"World"x, "color": "red"}
^
여기서는 x가 유효하지 않음을 나타냅니다.
입력 버퍼에는 const가 아닌 std::string
사용하는 것이 좋습니다. 이렇게 하면 Glaze가 임시 패딩으로 성능을 향상시키고 버퍼가 null로 종료될 수 있기 때문입니다.
기본적으로 null_terminated
옵션은 true
로 설정되어 있으며 JSON을 구문 분석할 때 null 종료 버퍼를 사용해야 합니다. 이 옵션은 성능이 약간 손실되면서 꺼질 수 있으며, 이는 null이 아닌 종료 버퍼를 허용합니다.
constexpr glz::opts options{. null_terminated = false };
auto ec = glz::read<options>(value, buffer); // read in a non-null terminated buffer
BEVE(바이너리)를 구문 분석할 때는 Null 종료가 필요하지 않습니다. 성능에는 차이가 없습니다.
경고
현재 null_terminated = false
CSV 구문 분석에 유효하지 않으며 버퍼는 null로 끝나야 합니다.
배열 유형은 논리적으로 JSON 배열 값으로 변환됩니다. 개념은 표준 라이브러리 인터페이스와 일치하는 경우 다양한 컨테이너는 물론 사용자 컨테이너까지 허용하는 데 사용됩니다.
glz::array
(컴파일 시간 혼합 유형)std::tuple
(컴파일 시간 혼합 유형)std::array
std::vector
std::deque
std::list
std::forward_list
std::span
std::set
std::unordered_set
객체 유형은 지도와 같은 JSON 객체 값으로 논리적으로 변환됩니다. JSON과 마찬가지로 Glaze는 객체 정의를 순서가 없는 맵으로 처리합니다. 따라서 개체 레이아웃의 순서는 C++의 동일한 이진 시퀀스와 일치할 필요가 없습니다.
glz::object
(컴파일 시간 혼합 유형)std::map
std::unordered_map
std::pair
(스택 저장소에서 동적 키를 활성화합니다)
std::pair
단일 키와 값을 가진 객체로 처리되지만,std::pair
배열에 사용되면 Glaze는 쌍을 단일 객체로 연결합니다.std::vector<std::pair<...>>
단일 객체로 직렬화됩니다. 이 동작을 원하지 않으면 컴파일 시간 옵션.concatenate = false
설정하세요.
std::variant
자세한 내용은 변형 처리를 참조하세요.
std::unique_ptr
std::shared_ptr
std::optional
널 입력 가능 유형은 유효한 입력으로 할당되거나 null
키워드로 널화될 수 있습니다.
std::unique_ptr< int > ptr{};
std::string buffer{};
expect ( not glz::write_json (ptr, buffer));
expect (buffer == " null " );
expect ( not glz::read_json (ptr, " 5 " ));
expect (*ptr == 5 );
buffer.clear();
expect ( not glz::write_json (ptr, buffer));
expect (buffer == " 5 " );
expect ( not glz::read_json (ptr, " null " ));
expect (! bool (ptr));
기본적으로 열거형은 정수 형식으로 작성되고 읽혀집니다. 이것이 원하는 동작이라면 glz::meta
필요하지 않습니다.
그러나 JSON에서 열거형을 문자열로 사용하려는 경우 다음과 같이 glz::meta
에 등록할 수 있습니다.
enum class Color { Red, Green, Blue };
template <>
struct glz ::meta<Color> {
using enum Color;
static constexpr auto value = enumerate(Red,
Green,
Blue
);
};
사용 중:
Color color = Color::Red;
std::string buffer{};
glz::write_json (color, buffer);
expect (buffer == " " Red " " );
주석은 여기에 정의된 사양으로 지원됩니다: JSONC
주석에 대한 읽기 지원은 glz::read_jsonc
또는 glz::read<glz::opts{.comments = true}>(...)
를 통해 제공됩니다.
형식화된 JSON은 컴파일 시간 옵션을 통해 직접 작성할 수 있습니다.
auto ec = glz::write<glz::opts{. prettify = true }>(obj, buffer);
또는 glz::prettify_json
함수를 사용하여 JSON 텍스트의 형식을 지정할 수 있습니다.
std::string buffer = R"( {"i":287,"d":3.14,"hello":"Hello World","arr":[1,2,3]} )" );
auto beautiful = glz::prettify_json(buffer);
지금은 beautiful
습니다:
{
"i" : 287 ,
"d" : 3.14 ,
"hello" : " Hello World " ,
"arr" : [
1 ,
2 ,
3
]
}
축소된 JSON을 작성하려면 다음을 수행하세요.
auto ec = glz::write_json(obj, buffer); // default is minified
JSON 텍스트 호출을 축소하려면:
std::string minified = glz::minify_json(buffer);
축소된 JSON이 필요하거나 입력이 항상 축소되는 것을 알고 싶다면 컴파일 시간 옵션 .minified = true
를 사용하여 성능을 조금 더 얻을 수 있습니다.
auto ec = glz::read<glz::opts{. minified = true }>(obj, buffer);
Glaze는 문자열 옵션의 배열처럼 동작하는 부울 플래그 세트 등록을 지원합니다:
struct flags_t {
bool x{ true };
bool y{};
bool z{ true };
};
template <>
struct glz ::meta< flags_t > {
using T = flags_t ;
static constexpr auto value = flags( " x " , &T::x, " y " , &T::y, " z " , &T::z);
};
예:
flags_t s{};
expect (glz::write_json(s) == R"([ " x " , " z " ])");
"x"
와 "z"
만 사실이므로 기록됩니다. 버퍼를 읽으면 적절한 부울이 설정됩니다.
BEVE를 작성할 때
flags
부울당 1비트만 사용합니다(바이트 정렬).
때로는 JSON 구조를 최대한 효율적으로 즉석에서 작성하고 싶을 때가 있습니다. Glaze는 할당 구조를 쌓아서 JSON을 고속으로 작성할 수 있는 튜플과 같은 구조를 제공합니다. 이러한 구조의 이름은 객체의 경우 glz::obj
이고 배열의 경우 glz::arr
.
다음은 배열도 포함하는 객체를 만들고 이를 작성하는 예입니다.
auto obj = glz::obj{ " pi " , 3.14 , " happy " , true , " name " , " Stephen " , " arr " , glz::arr{ " Hello " , " World " , 2 }};
std::string s{};
expect ( not glz::write_json (obj, s));
expect (s == R"( {"pi":3.14,"happy":true,"name":"Stephen","arr":["Hello","World",2]} )" );
이 접근 방식은 일반 JSON의
glz::json_t
보다 훨씬 빠릅니다. 그러나 모든 상황에 적합하지 않을 수도 있습니다.
glz::merge
하면 사용자가 여러 JSON 개체 유형을 단일 개체로 병합할 수 있습니다.
glz::obj o{ " pi " , 3.141 };
std::map<std::string_view, int > map = {{ " a " , 1 }, { " b " , 2 }, { " c " , 3 }};
auto merged = glz::merge{o, map};
std::string s{};
glz::write_json (merged, s); // will write out a single, merged object
// s is now: {"pi":3.141,"a":0,"b":2,"c":3}
glz::merge
복사본을 피하기 위해 lvalue에 대한 참조를 저장합니다.
glz::json_t
에 대한 일반 JSON을 참조하세요.
glz:: json_t json{};
std::string buffer = R"( [5,"Hello World",{"pi":3.14}] )" ;
glz::read_json (json, buffer);
assert (json[ 2 ][ " pi " ].get< double >() == 3.14);
Glaze는 원시 문자 버퍼에 쓰는 것만큼 std::string
에 쓰는 속도가 빠릅니다. 버퍼에 공간을 충분히 할당했다면 아래와 같이 원시 버퍼에 쓸 수 있지만 권장되지는 않습니다.
glz::read_json(obj, buffer);
const auto n = glz::write_json(obj, buffer.data()).value_or(0);
buffer.resize(n);
glz::opts
구조체는 읽기/쓰기를 위한 컴파일 시간 선택적 설정을 정의합니다.
glz::read_json(...)
호출하는 대신 glz::read<glz::opts{}>(...)
호출하고 옵션을 사용자 정의할 수 있습니다.
예를 들어, glz::read<glz::opts{.error_on_unknown_keys = false}>(...)
알 수 없는 키에 대한 오류를 끄고 항목을 건너뜁니다.
glz::opts
형식을 전환할 수도 있습니다:
glz::read<glz::opts{.format = glz::BEVE}>(...)
-> glz::read_beve(...)
glz::read<glz::opts{.format = glz::JSON}>(...)
-> glz::read_json(...)
아래 구조체는 사용 가능한 옵션과 기본 동작을 보여줍니다.
struct opts {
uint32_t format = json;
bool comments = false ; // Support reading in JSONC style comments
bool error_on_unknown_keys = true ; // Error when an unknown key is encountered
bool skip_null_members = true ; // Skip writing out params in an object if the value is null
bool use_hash_comparison = true ; // Will replace some string equality checks with hash checks
bool prettify = false ; // Write out prettified JSON
bool minified = false ; // Require minified input for JSON, which results in faster read performance
char indentation_char = ' ' ; // Prettified JSON indentation char
uint8_t indentation_width = 3 ; // Prettified JSON indentation size
bool new_lines_in_arrays = true ; // Whether prettified arrays should have new lines for each element
bool shrink_to_fit = false ; // Shrinks dynamic containers to new size to save memory
bool write_type_info = true ; // Write type info for meta objects in variants
bool error_on_missing_keys = false ; // Require all non nullable keys to be present in the object. Use
// skip_null_members = false to require nullable members
bool error_on_const_read =
false ; // Error if attempt is made to read into a const value, by default the value is skipped without error
bool validate_skipped = false ; // If full validation should be performed on skipped values
bool validate_trailing_whitespace =
false ; // If, after parsing a value, we want to validate the trailing whitespace
uint8_t layout = rowwise; // CSV row wise output/input
// The maximum precision type used for writing floats, higher precision floats will be cast down to this precision
float_precision float_max_write_precision{};
bool bools_as_numbers = false ; // Read and write booleans with 1's and 0's
bool quoted_num = false ; // treat numbers as quoted or array-like types as having quoted numbers
bool number = false ; // read numbers as strings and write these string as numbers
bool raw = false ; // write out string like values without quotes
bool raw_string =
false ; // do not decode/encode escaped characters for strings (improves read/write performance)
bool structs_as_arrays = false ; // Handle structs (reading/writing) without keys, which applies
bool allow_conversions = true ; // Whether conversions between convertible types are
// allowed in binary, e.g. double -> float
bool partial_read =
false ; // Reads into only existing fields and elements and then exits without parsing the rest of the input
// glaze_object_t concepts
bool partial_read_nested = false ; // Advance the partially read struct to the end of the struct
bool concatenate = true ; // Concatenates ranges of std::pair into single objects when writing
bool hide_non_invocable =
true ; // Hides non-invocable members from the cli_menu (may be applied elsewhere in the future)
};
이러한 컴파일 시간 옵션 중 다수에는 옵션을 단일 필드에만 적용하는 래퍼가 있습니다. 자세한 내용은 래퍼를 참조하세요.
기본적으로 Glaze는 관련 옵션이 있는 두 가지 경우를 제외하고 최신 JSON 표준을 엄격하게 준수합니다.
validate_skipped
이 옵션은 구문 분석 시 건너뛴 값에 대해 전체 JSON 유효성 검사를 수행합니다. 이는 사용자가 값에 관심이 없을 때 일반적으로 값을 건너뛰고 Glaze가 여전히 주요 문제를 확인하기 때문에 기본적으로 설정되지 않습니다. 하지만 이렇게 하면 건너뛴 값이 정확히 JSON을 준수하는지 신경 쓰지 않아 건너뛰기가 더 빨라집니다. 예를 들어 기본적으로 Glaze는 건너뛴 숫자에 유효한 숫자가 모두 포함되어 있는지 확인하지만, validate_skipped
켜져 있지 않으면 건너뛴 숫자의 앞에 오는 0과 같은 문제에 대해서는 유효성을 검사하지 않습니다. Glaze가 사용할 값을 구문 분석할 때마다 완전히 검증됩니다.validate_trailing_whitespace
이 옵션은 구문 분석된 문서에서 후행 공백의 유효성을 검사합니다. Glaze는 C++ 구조체를 구문 분석하기 때문에 일반적으로 관심 객체를 읽은 후에 구문 분석을 계속할 필요가 없습니다. 문서의 나머지 부분에 유효한 공백이 있는지 확인하려면 이 옵션을 켜십시오. 그렇지 않으면 Glaze는 관심 있는 내용이 구문 분석된 후 해당 내용을 무시합니다. 메모
Glaze는 이스케이프 제어 문자(예: "x1f"
~ "u001f"
)를 자동으로 유니코드하지 않습니다. 이는 문자열에 널 문자 및 기타 보이지 않는 문자가 포함될 위험이 있기 때문입니다. 이러한 변환(공개 문제: 유니코드 이스케이프 쓰기)을 활성화하기 위해 컴파일 시간 옵션이 추가되지만 기본 동작은 아닙니다.
오류를 방지하기 위해 개체에 키 존재를 확인하는 것이 유용할 수 있지만 C++에서는 값이 필요하지 않거나 존재하지 않을 수 있습니다. 이러한 경우는 메타 데이터에 glz::skip
유형을 등록하여 처리됩니다.
struct S {
int i{};
};
template <>
struct glz ::meta<S> {
static constexpr auto value = object( " key_to_skip " , skip{}, &S::i);
};
std::string buffer = R"( {"key_to_skip": [1,2,3], "i": 7} )" ;
S s{};
glz::read_json (s, buffer);
// The value [1,2,3] will be skipped
expect (s.i == 7 ); // only the value i will be read into
Glaze는 일반 API 구축을 돕기 위해 설계되었습니다. 때로는 값을 API에 노출해야 하지만 JSON에서 값을 읽거나 쓰는 것은 바람직하지 않습니다. 이것은 glz::hide
의 사용 사례입니다.
glz::hide
API(및 JSON 포인터) 액세스를 허용하면서 JSON 출력에서 값을 숨깁니다.
struct hide_struct {
int i = 287 ;
double d = 3.14 ;
std::string hello = " Hello World " ;
};
template <>
struct glz ::meta<hide_struct> {
using T = hide_struct;
static constexpr auto value = object(&T::i, //
&T::d, //
" hello " , hide{&T::hello});
};
hide_struct s{};
auto b = glz::write_json(s);
expect (b == R"( {"i":287,"d":3.14} )" ); // notice that "hello" is hidden from the output
glz::quoted
래퍼를 활용하여 인용된 JSON 숫자를 double
, int
등과 같은 유형으로 직접 구문 분석할 수 있습니다.
struct A {
double x;
std::vector< uint32_t > y;
};
template <>
struct glz ::meta<A> {
static constexpr auto value = object( " x " , glz::quoted_num<&A::x>, " y " , glz::quoted_num<&A::y>;
};
{
"x" : " 3.14 " ,
"y" : [ " 1 " , " 2 " , " 3 " ]
}
인용된 JSON 숫자는 double
및 std::vector<uint32_t>
로 직접 구문 분석됩니다. glz::quoted
함수는 중첩된 객체와 배열에도 작동합니다.
Glaze는 배열과 유사한 유형(예: std::vector
및 std::tuple
)에 대해 JSON Lines(또는 Newline Delimited JSON)을 지원합니다.
std::vector<std::string> x = { " Hello " , " World " , " Ice " , " Cream " };
std::string s = glz::write_ndjson(x).value_or( " error " );
auto ec = glz::read_ndjson(x, s);
확장에 대해서는 ext
디렉토리를 참조하십시오.
Glaze는 포함된 형식을 제외하고 MIT 라이선스에 따라 배포됩니다.
--- 라이센스에 대한 선택적 예외 ---
예외적으로, 소스 코드를 컴파일한 결과 이 소프트웨어의 일부가 해당 소스 코드의 기계 실행 가능한 개체 형태에 포함된 경우 저작권 및 허가를 포함하지 않고 해당 개체 형식에 포함된 부분을 재배포할 수 있습니다. 통지.