Una de las bibliotecas JSON más rápidas del mundo. Glaze lee y escribe desde la memoria de objetos, simplificando las interfaces y ofreciendo un rendimiento increíble.
Glaze también admite:
Reflexión pura en tiempo de compilación para estructuras.
Cumplimiento de JSON RFC 8259 con validación UTF-8
Soporte de biblioteca estándar C++
Sólo encabezado
Serialización/deserialización directa a memoria
Compile mapas de tiempo con búsquedas de tiempo constantes y hash perfecto
Potentes contenedores para modificar el comportamiento de lectura/escritura (Wrappers)
Utilice sus propias funciones personalizadas de lectura/escritura (lectura/escritura personalizada)
Maneja claves desconocidas de forma rápida y flexible
Acceso directo a la memoria a través de la sintaxis del puntero JSON
Datos binarios a través de la misma API para un máximo rendimiento
Sin excepciones (se compila con -fno-exceptions
)
No se necesita información del tipo de tiempo de ejecución (se compila con -fno-rtti
)
Manejo rápido de errores con cortocircuito
Soporte JSON-RPC 2.0
Generación de esquema JSON
Extremadamente portátil, utiliza SWAR (SIMD dentro de un registro) cuidadosamente optimizado para una amplia compatibilidad
Soporte de lectura parcial y escritura parcial
Lectura/Escritura CSV
¡Mucho más!
Consulte DOCS para obtener más documentación.
Biblioteca | Tiempo(s) de ida y vuelta | Escritura (MB/s) | Lectura (MB/s) |
---|---|---|---|
Vidriado | 1.04 | 1366 | 1224 |
simdjson (bajo demanda) | N / A | N / A | 1198 |
yyjson | 1.23 | 1005 | 1107 |
enlace_daw_json | 2.93 | 365 | 553 |
RapidJSON | 3.65 | 290 | 450 |
Boost.JSON (directo) | 4.76 | 199 | 447 |
json_struct | 5.50 | 182 | 326 |
nlohmann | 15.71 | 84 | 80 |
Código de prueba de rendimiento disponible aquí
Advertencias de rendimiento: simdjson y yyjson son excelentes, pero experimentan pérdidas importantes de rendimiento cuando los datos no están en la secuencia esperada o falta alguna clave (el problema crece a medida que aumenta el tamaño del archivo, ya que deben repetirse a través del documento).
Además, simdjson y yyjson no admiten el manejo automático de cadenas con escape, por lo que si alguna de las cadenas actualmente sin escape en este punto de referencia contuviera un escape, los escapes no se manejarían.
La prueba ABC muestra cómo simdjson tiene un rendimiento deficiente cuando las claves no están en la secuencia esperada:
Biblioteca | Lectura (MB/s) |
---|---|
Vidriado | 678 |
simdjson (bajo demanda) | 93 |
Especificación binaria etiquetada: BEVE
Métrico | Tiempo(s) de ida y vuelta | Escritura (MB/s) | Lectura (MB/s) |
---|---|---|---|
Rendimiento bruto | 0,42 | 3235 | 2468 |
Datos JSON equivalentes* | 0,42 | 3547 | 2706 |
Tamaño JSON: 670 bytes
Tamaño BEVE: 611 bytes
*BEVE empaqueta de manera más eficiente que JSON, por lo que transportar los mismos datos es aún más rápido.
¡Tu estructura se reflejará automáticamente! El usuario no requiere metadatos.
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 (embellecido)
{
"i" : 287 ,
"d" : 3.14 ,
"hello" : " Hello World " ,
"arr" : [
1 ,
2 ,
3
],
"map" : {
"one" : 1 ,
"two" : 2
}
}
Escribir JSON
my_struct s{};
std::string buffer = glz::write_json(s).value_or( " error " );
o
my_struct s{};
std::string buffer{};
auto ec = glz::write_json(s, buffer);
if (ec) {
// handle error
}
Leer 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
}
o
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{});
Importante
El nombre del archivo (segundo argumento) debe terminar en nulo.
Las acciones se crean y prueban con Clang (17+), MSVC (2022) y GCC (12+) en Apple, Windows y Linux.
Glaze busca mantener la compatibilidad con las tres últimas versiones de GCC y Clang, así como con la última versión de MSVC y Apple Clang.
Glaze requiere un preprocesador compatible con el estándar C++, que requiere el indicador /Zc:preprocessor
cuando se compila con MSVC.
El CMake tiene la opción glaze_ENABLE_AVX2
. Esto intentará utilizar las instrucciones AVX2
SIMD en algunos casos para mejorar el rendimiento, siempre que el sistema en el que esté configurando lo admita. Establezca esta opción en OFF
para deshabilitar el conjunto de instrucciones AVX2, por ejemplo, si está realizando una compilación cruzada para Arm. Si no está utilizando CMake, la macro GLZ_USE_AVX2
habilita la función si está definida.
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}
Si desea especializar su reflexión, opcionalmente puede escribir el siguiente código:
Estos metadatos también son necesarios para estructuras inicializables no agregadas.
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
);
};
};
Cuando define metadatos de Glaze, los objetos reflejarán automáticamente los nombres no estáticos de los punteros de sus objetos miembros. Sin embargo, si desea nombres personalizados o registra funciones lambda o contenedores que no proporcionan nombres para sus campos, opcionalmente puede agregar nombres de campos en sus metadatos.
Ejemplo de nombres personalizados:
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
);
};
Cada una de estas cadenas es opcional y se puede eliminar para campos individuales si desea que se refleje el nombre.
Se requieren nombres para:
- variables miembro estáticas de constexpr
- Envoltorios
- funciones lambda
Glaze proporciona una API de reflexión en tiempo de compilación que se puede modificar mediante especializaciones glz::meta
. Esta API de reflexión utiliza reflexión pura a menos que se proporcione una especialización glz::meta
, en cuyo caso el desarrollador anula el comportamiento predeterminado.
static_assert (glz::reflect<my_struct>::size == 5 ); // Number of fields
static_assert (glz::reflect<my_struct>::keys[ 0 ] == " i " ); // Access keys
Advertencia
Los campos glz::reflect
descritos anteriormente se han formalizado y es poco probable que cambien. Otros campos dentro de la glz::reflect
pueden evolucionar a medida que continuamos formalizando la especificación. Por lo tanto, es posible que se produzcan cambios importantes en campos no documentados en el futuro.
La lectura y escritura personalizadas se pueden lograr a través del poderoso enfoque de especialización to
/ from
, que se describe aquí: custom-serialization.md. Sin embargo, esto sólo funciona para tipos definidos por el usuario.
Para casos de uso comunes o casos en los que una variable miembro específica debe tener lectura y escritura especiales, puede usar glz::custom
para registrar funciones miembro de lectura/escritura, std::functions o funciones lambda.
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]} )" );
};
};
Cuando se utilizan punteros de miembros (por ejemplo, &T::a
), las estructuras de clases de C++ deben coincidir con la interfaz JSON. Puede resultar conveniente asignar clases de C++ con diseños diferentes a la misma interfaz de objeto. Esto se logra registrando funciones lambda en lugar de punteros de miembros.
template <>
struct glz ::meta<Thing> {
static constexpr auto value = object(
" i " , []( auto && self) -> auto & { return self. subclass . i ; }
);
};
El valor que se pasa self
a la función lambda será un objeto Thing
, y la función lambda nos permite hacer que la subclase sea invisible para la interfaz del objeto.
Lambda funciona mediante retornos de copia predeterminados, por lo que normalmente se requiere el tipo de retorno auto&
para que Glaseado escriba en la memoria.
Tenga en cuenta que la reasignación también se puede lograr mediante punteros/referencias, ya que el esmalte trata los valores, punteros y referencias de la misma manera al escribir/leer.
Una clase se puede tratar como un valor subyacente de la siguiente manera:
struct S {
int x{};
};
template <>
struct glz ::meta<S> {
static constexpr auto value{ &S::x };
};
o usando una lambda:
template <>
struct glz ::meta<S> {
static constexpr auto value = []( auto & self) -> auto & { return self. x ; };
};
Glaze es seguro de usar con mensajes que no son de confianza. Los errores se devuelven como códigos de error, normalmente dentro de un glz::expected
, que se comporta como un std::expected
.
Glaze trabaja para cortocircuitar el manejo de errores, lo que significa que el análisis sale muy rápidamente si se encuentra un error.
Para generar mensajes de error más útiles, llame format_error
:
auto pe = glz::read_json(obj, buffer);
if (pe) {
std::string descriptive_error = glz::format_error (pe, buffer);
}
Este caso de prueba:
{ "Hello" : " World " x, "color": "red" }
Produce este error:
1:17: expected_comma
{"Hello":"World"x, "color": "red"}
^
Denotando que x no es válido aquí.
Se recomienda un std::string
no constante para los buffers de entrada, ya que esto permite a Glaze mejorar el rendimiento con relleno temporal y el buffer terminará en nulo.
De forma predeterminada, la opción null_terminated
está configurada en true
y se deben usar búferes terminados en nulo al analizar JSON. La opción se puede desactivar con una pequeña pérdida de rendimiento, lo que permite búferes terminados no en nulos:
constexpr glz::opts options{. null_terminated = false };
auto ec = glz::read<options>(value, buffer); // read in a non-null terminated buffer
No se requiere terminación nula al analizar BEVE (binario). No hace ninguna diferencia en el rendimiento.
Advertencia
Actualmente, null_terminated = false
no es válido para el análisis de CSV y los búferes deben tener terminación nula.
Los tipos de matriz se convierten lógicamente a valores de matriz JSON. Los conceptos se utilizan para permitir varios contenedores e incluso contenedores de usuario si coinciden con las interfaces de biblioteca estándar.
glz::array
(tipos mixtos en tiempo de compilación)std::tuple
(tipos mixtos en tiempo de compilación)std::array
std::vector
std::deque
std::list
std::forward_list
std::span
std::set
std::unordered_set
Los tipos de objetos se convierten lógicamente a valores de objetos JSON, como mapas. Al igual que JSON, Glaze trata las definiciones de objetos como mapas desordenados. Por lo tanto, el orden del diseño de un objeto no tiene que coincidir con la misma secuencia binaria en C++.
glz::object
(tipos mixtos en tiempo de compilación)std::map
std::unordered_map
std::pair
(habilita claves dinámicas en el almacenamiento de pila)
std::pair
se maneja como un objeto con una única clave y valor, pero cuandostd::pair
se usa en una matriz, Glaze concatena los pares en un solo objeto.std::vector<std::pair<...>>
se serializará como un solo objeto. Si no desea este comportamiento, configure la opción de tiempo de compilación.concatenate = false
.
std::variant
Consulte Manejo de variantes para obtener más información.
std::unique_ptr
std::shared_ptr
std::optional
Los tipos que aceptan valores NULL pueden asignarse mediante una entrada válida o anularse mediante la palabra clave 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));
De forma predeterminada, las enumeraciones se escribirán y leerán en forma de números enteros. No es necesario glz::meta
si este es el comportamiento deseado.
Sin embargo, si prefiere utilizar enumeraciones como cadenas en JSON, se pueden registrar en glz::meta
de la siguiente manera:
enum class Color { Red, Green, Blue };
template <>
struct glz ::meta<Color> {
using enum Color;
static constexpr auto value = enumerate(Red,
Green,
Blue
);
};
En uso:
Color color = Color::Red;
std::string buffer{};
glz::write_json (color, buffer);
expect (buffer == " " Red " " );
Los comentarios son compatibles con la especificación definida aquí: JSONC
El soporte de lectura para comentarios se proporciona con glz::read_jsonc
o glz::read<glz::opts{.comments = true}>(...)
.
El JSON formateado se puede escribir directamente mediante una opción de tiempo de compilación:
auto ec = glz::write<glz::opts{. prettify = true }>(obj, buffer);
O bien, el texto JSON se puede formatear con la función glz::prettify_json
:
std::string buffer = R"( {"i":287,"d":3.14,"hello":"Hello World","arr":[1,2,3]} )" );
auto beautiful = glz::prettify_json(buffer);
beautiful
es ahora:
{
"i" : 287 ,
"d" : 3.14 ,
"hello" : " Hello World " ,
"arr" : [
1 ,
2 ,
3
]
}
Para escribir JSON minimizado:
auto ec = glz::write_json(obj, buffer); // default is minified
Para minimizar la llamada de texto JSON:
std::string minified = glz::minify_json(buffer);
Si desea requerir JSON minimizado o sabe que su entrada siempre será minimizada, puede obtener un poco más de rendimiento utilizando la opción de tiempo de compilación .minified = true
.
auto ec = glz::read<glz::opts{. minified = true }>(obj, buffer);
Glaze admite el registro de un conjunto de indicadores booleanos que se comportan como una serie de opciones de cadena:
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);
};
Ejemplo:
flags_t s{};
expect (glz::write_json(s) == R"([ " x " , " z " ])");
Sólo se escriben "x"
y "z"
, porque son verdaderas. La lectura en el búfer establecerá los valores booleanos apropiados.
Al escribir BEVE,
flags
solo usan un bit por booleano (byte alineado).
A veces lo único que desea es escribir estructuras JSON sobre la marcha de la manera más eficiente posible. Glaze proporciona estructuras tipo tupla que le permiten apilar estructuras asignadas para escribir JSON a alta velocidad. Estas estructuras se denominan glz::obj
para objetos y glz::arr
para matrices.
A continuación se muestra un ejemplo de cómo construir un objeto, que también contiene una matriz, y escribirlo.
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]} )" );
Este enfoque es significativamente más rápido que
glz::json_t
para JSON genérico. Sin embargo, puede que no sea adecuado para todos los contextos.
glz::merge
permite al usuario fusionar varios tipos de objetos JSON en un solo objeto.
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
almacena referencias a valores l para evitar copias
Consulte JSON genérico para glz::json_t
.
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 escribe casi tan rápido en un std::string
como lo hace en un búfer de caracteres sin formato. Si tiene suficiente espacio asignado en su búfer, puede escribir en el búfer sin formato, como se muestra a continuación, pero no se recomienda.
glz::read_json(obj, buffer);
const auto n = glz::write_json(obj, buffer.data()).value_or(0);
buffer.resize(n);
La estructura glz::opts
define configuraciones opcionales en tiempo de compilación para lectura/escritura.
En lugar de llamar glz::read_json(...)
, puede llamar glz::read<glz::opts{}>(...)
y personalizar las opciones.
Por ejemplo: glz::read<glz::opts{.error_on_unknown_keys = false}>(...)
desactivará los errores en claves desconocidas y simplemente omitirá los elementos.
glz::opts
también puede cambiar entre formatos:
glz::read<glz::opts{.format = glz::BEVE}>(...)
-> glz::read_beve(...)
glz::read<glz::opts{.format = glz::JSON}>(...)
-> glz::read_json(...)
La siguiente estructura muestra las opciones disponibles y el comportamiento predeterminado.
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)
};
Muchas de estas opciones de tiempo de compilación tienen contenedores para aplicar la opción a un solo campo. Consulte Wrappers para obtener más detalles.
De forma predeterminada, Glaze cumple estrictamente con el último estándar JSON, excepto en dos casos con opciones asociadas:
validate_skipped
Esta opción realiza una validación JSON completa para los valores omitidos al analizar. Esto no está configurado de forma predeterminada porque los valores generalmente se omiten cuando el usuario no está interesado en ellos, y Glaze aún valida para problemas importantes. Pero esto hace que omitir sea más rápido al no importarle si los valores omitidos son exactamente compatibles con JSON. Por ejemplo, de forma predeterminada, Glaze garantizará que los números omitidos tengan todos los caracteres numéricos válidos, pero no validará problemas como ceros a la izquierda en números omitidos a menos que validate_skipped
esté activado. Siempre que Glaze analiza un valor para utilizarlo, se valida por completo.validate_trailing_whitespace
Esta opción valida el espacio en blanco final en un documento analizado. Debido a que Glaze analiza estructuras de C++, normalmente no es necesario continuar analizando después de que se haya leído el objeto de interés. Active esta opción si desea asegurarse de que el resto del documento tenga espacios en blanco válidos; de lo contrario, Glaze simplemente ignorará el contenido después de que se haya analizado el contenido de interés. Nota
Glaze no codifica automáticamente los caracteres de control de escape (por ejemplo, "x1f"
a "u001f"
), ya que esto plantea el riesgo de incrustar caracteres nulos y otros caracteres invisibles en las cadenas. Se agregará una opción de tiempo de compilación para habilitar estas conversiones (problema abierto: escritura de escape Unicode), pero no será el comportamiento predeterminado.
Puede resultar útil reconocer la existencia de una clave en un objeto para evitar errores y, sin embargo, es posible que el valor no sea necesario o no exista en C++. Estos casos se manejan registrando un glz::skip
con los metadatos.
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 está diseñado para ayudar a crear API genéricas. A veces es necesario exponer un valor a la API, pero no es deseable leer o escribir el valor en JSON. Este es el caso de uso de glz::hide
.
glz::hide
oculta el valor de la salida JSON y al mismo tiempo permite el acceso a la API (y al puntero 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
Puede analizar números JSON entre comillas directamente en tipos como double
, int
, etc. utilizando el contenedor glz::quoted
.
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 " ]
}
Los números JSON citados se analizarán directamente en double
y std::vector<uint32_t>
. La función glz::quoted
también funciona para objetos y matrices anidados.
Glaze admite líneas JSON (o JSON delimitado por nueva línea) para tipos similares a matrices (por ejemplo, std::vector
y std::tuple
).
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);
Consulte el directorio ext
para ver las extensiones.
Glaze se distribuye bajo la licencia MIT con excepción de los formularios integrados:
--- Excepción opcional a la licencia ---
Como excepción, si, como resultado de la compilación de su código fuente, partes de este Software están integradas en una forma de objeto ejecutable por máquina de dicho código fuente, puede redistribuir dichas partes incrustadas en dicha forma de objeto sin incluir los derechos de autor ni el permiso. avisos.