L'une des bibliothèques JSON les plus rapides au monde. Glaze lit et écrit à partir de la mémoire objet, simplifiant les interfaces et offrant des performances incroyables.
Glaze prend également en charge :
Réflexion pure au moment de la compilation pour les structures
Conformité JSON RFC 8259 avec validation UTF-8
Prise en charge de la bibliothèque C++ standard
En-tête uniquement
Sérialisation/désérialisation directe vers la mémoire
Compilez des cartes temporelles avec des recherches en temps constant et un hachage parfait
Wrappers puissants pour modifier le comportement de lecture/écriture (Wrappers)
Utilisez vos propres fonctions de lecture/écriture personnalisées (Custom Read/Write)
Gérez les clés inconnues de manière rapide et flexible
Accès direct à la mémoire via la syntaxe du pointeur JSON
Données binaires via la même API pour des performances maximales
Aucune exception (compile avec -fno-exceptions
)
Aucune information de type d'exécution nécessaire (compile avec -fno-rtti
)
Gestion rapide des erreurs avec court-circuit
Prise en charge de JSON-RPC 2.0
Génération de schéma JSON
Extrêmement portable, utilise SWAR (SIMD Within A Register) soigneusement optimisé pour une large compatibilité
Prise en charge de la lecture partielle et de l'écriture partielle
Lecture/écriture CSV
Bien plus encore !
Voir DOCS pour plus de documentation.
Bibliothèque | Temps (s) aller-retour | Écrire (Mo/s) | Lecture (Mo/s) |
---|---|---|---|
Lustre | 1.04 | 1366 | 1224 |
simdjson (sur demande) | N / A | N / A | 1198 |
yyjson | 1.23 | 1005 | 1107 |
daw_json_link | 2,93 | 365 | 553 |
RapidJSON | 3,65 | 290 | 450 |
Boost.JSON (direct) | 4,76 | 199 | 447 |
json_struct | 5,50 | 182 | 326 |
nlohmann | 15.71 | 84 | 80 |
Code de test de performances disponible ici
Avertissements en matière de performances : simdjson et yyjson sont excellents, mais ils subissent des pertes de performances importantes lorsque les données ne se trouvent pas dans la séquence attendue ou que des clés sont manquantes (le problème s'aggrave à mesure que la taille du fichier augmente, car ils doivent réitérer le document).
De plus, simdjson et yyjson ne prennent pas en charge la gestion automatique des chaînes d'échappement, donc si l'une des chaînes actuellement non échappées dans ce test devait contenir un échappement, les échappements ne seraient pas gérés.
Le test ABC montre à quel point simdjson a de mauvaises performances lorsque les touches ne sont pas dans l'ordre attendu :
Bibliothèque | Lecture (Mo/s) |
---|---|
Lustre | 678 |
simdjson (sur demande) | 93 |
Spécification binaire étiquetée : BEVE
Métrique | Temps (s) aller-retour | Écrire (Mo/s) | Lecture (Mo/s) |
---|---|---|---|
Performances brutes | 0,42 | 3235 | 2468 |
Données JSON équivalentes* | 0,42 | 3547 | 2706 |
Taille JSON : 670 octets
Taille BEVE : 611 octets
*BEVE emballe plus efficacement que JSON, donc le transport des mêmes données est encore plus rapide.
Votre structure sera automatiquement reflétée ! Aucune métadonnée n'est requise par l'utilisateur.
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 (joli)
{
"i" : 287 ,
"d" : 3.14 ,
"hello" : " Hello World " ,
"arr" : [
1 ,
2 ,
3
],
"map" : {
"one" : 1 ,
"two" : 2
}
}
Écrire du JSON
my_struct s{};
std::string buffer = glz::write_json(s).value_or( " error " );
ou
my_struct s{};
std::string buffer{};
auto ec = glz::write_json(s, buffer);
if (ec) {
// handle error
}
Lire 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
}
ou
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{});
Important
Le nom du fichier (2ème argument) doit se terminer par un caractère nul.
Actions créées et testées avec Clang (17+), MSVC (2022) et GCC (12+) sur Apple, Windows et Linux.
Glaze cherche à maintenir la compatibilité avec les trois dernières versions de GCC et Clang, ainsi qu'avec la dernière version de MSVC et Apple Clang.
Glaze nécessite un préprocesseur conforme à la norme C++, qui nécessite l'indicateur /Zc:preprocessor
lors de la construction avec MSVC.
Le CMake a l' glaze_ENABLE_AVX2
. Cela tentera d'utiliser les instructions AVX2
SIMD dans certains cas pour améliorer les performances, à condition que le système sur lequel vous configurez le prenne en charge. Définissez cette option sur OFF
pour désactiver le jeu d’instructions AVX2, par exemple si vous effectuez une compilation croisée pour Arm. Si vous n'utilisez pas CMake, la macro GLZ_USE_AVX2
active la fonctionnalité si elle est définie.
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 vous souhaitez spécialiser votre réflexion alors vous pouvez éventuellement écrire le code ci-dessous :
Ces métadonnées sont également nécessaires pour les structures initialisables non agrégées.
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
);
};
};
Lorsque vous définissez les métadonnées Glaze, les objets refléteront automatiquement les noms non statiques de vos pointeurs d'objets membres. Cependant, si vous souhaitez des noms personnalisés ou si vous enregistrez des fonctions ou des wrappers lambda qui ne fournissent pas de noms pour vos champs, vous pouvez éventuellement ajouter des noms de champs dans vos métadonnées.
Exemple de noms personnalisés :
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
);
};
Chacune de ces chaînes est facultative et peut être supprimée pour des champs individuels si vous souhaitez que le nom soit reflété.
Les noms sont requis pour :
- variables membres constexpr statiques
- Emballages
- Fonctions Lambda
Glaze fournit une API de réflexion au moment de la compilation qui peut être modifiée via les spécialisations glz::meta
. Cette API de réflexion utilise la réflexion pure sauf si une spécialisation glz::meta
est fournie, auquel cas le comportement par défaut est remplacé par le développeur.
static_assert (glz::reflect<my_struct>::size == 5 ); // Number of fields
static_assert (glz::reflect<my_struct>::keys[ 0 ] == " i " ); // Access keys
Avertissement
Les champs glz::reflect
décrits ci-dessus ont été formalisés et il est peu probable qu'ils changent. D'autres champs au sein de la structure glz::reflect
peuvent évoluer à mesure que nous continuons à formaliser la spécification. Par conséquent, des modifications avec rupture peuvent survenir à l’avenir pour les champs non documentés.
La lecture et l'écriture personnalisées peuvent être obtenues grâce à la puissante approche de spécialisation to
/ from
, décrite ici : custom-serialization.md. Cependant, cela ne fonctionne que pour les types définis par l'utilisateur.
Pour les cas d'utilisation courants ou les cas où une variable membre spécifique doit avoir une lecture et une écriture spéciales, vous pouvez utiliser glz::custom
pour enregistrer les fonctions membres en lecture/écriture, std::functions ou les fonctions 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]} )" );
};
};
Lorsque vous utilisez des pointeurs de membre (par exemple &T::a
), les structures de classe C++ doivent correspondre à l'interface JSON. Il peut être souhaitable de mapper des classes C++ avec des présentations différentes sur la même interface objet. Ceci est accompli en enregistrant des fonctions lambda au lieu de pointeurs de membre.
template <>
struct glz ::meta<Thing> {
static constexpr auto value = object(
" i " , []( auto && self) -> auto & { return self. subclass . i ; }
);
};
La valeur self
passée à la fonction lambda sera un objet Thing
, et la fonction lambda nous permet de rendre la sous-classe invisible à l'interface objet.
Les fonctions Lambda par défaut copient les retours, donc le type de retour auto&
est généralement requis pour que Glaze puisse écrire dans la mémoire.
Notez que le remappage peut également être réalisé via des pointeurs/références, car Glaze traite les valeurs, les pointeurs et les références de la même manière lors de l'écriture/lecture.
Une classe peut être traitée comme une valeur sous-jacente comme suit :
struct S {
int x{};
};
template <>
struct glz ::meta<S> {
static constexpr auto value{ &S::x };
};
ou en utilisant un lambda :
template <>
struct glz ::meta<S> {
static constexpr auto value = []( auto & self) -> auto & { return self. x ; };
};
Glaze peut être utilisé en toute sécurité avec des messages non fiables. Les erreurs sont renvoyées sous forme de codes d'erreur, généralement dans un glz::expected
, qui se comporte comme un std::expected
.
Glaze fonctionne pour court-circuiter la gestion des erreurs, ce qui signifie que l'analyse se termine très rapidement si une erreur est rencontrée.
Pour générer des messages d'erreur plus utiles, appelez format_error
:
auto pe = glz::read_json(obj, buffer);
if (pe) {
std::string descriptive_error = glz::format_error (pe, buffer);
}
Ce cas de test :
{ "Hello" : " World " x, "color": "red" }
Produit cette erreur :
1:17: expected_comma
{"Hello":"World"x, "color": "red"}
^
Indique que x n'est pas valide ici.
Un std::string
non const est recommandé pour les tampons d'entrée, car cela permet à Glaze d'améliorer les performances avec un remplissage temporaire et le tampon sera terminé par un nul.
Par défaut, l'option null_terminated
est définie sur true
et des tampons terminés par un caractère nul doivent être utilisés lors de l'analyse de JSON. L'option peut être désactivée avec une légère perte de performances, ce qui autorise des tampons terminés par des valeurs non nulles :
constexpr glz::opts options{. null_terminated = false };
auto ec = glz::read<options>(value, buffer); // read in a non-null terminated buffer
La terminaison nulle n'est pas requise lors de l'analyse de BEVE (binaire). Cela ne fait aucune différence en termes de performances.
Avertissement
Actuellement, null_terminated = false
n'est pas valide pour l'analyse CSV et les tampons doivent avoir une terminaison nulle.
Les types de tableau sont logiquement convertis en valeurs de tableau JSON. Les concepts sont utilisés pour autoriser divers conteneurs et même des conteneurs utilisateur s'ils correspondent aux interfaces de bibliothèque standard.
glz::array
(types mixtes au moment de la compilation)std::tuple
(types mixtes au moment de la compilation)std::array
std::vector
std::deque
std::list
std::forward_list
std::span
std::set
std::unordered_set
Les types d'objets sont logiquement convertis en valeurs d'objet JSON, telles que des cartes. Comme JSON, Glaze traite les définitions d'objets comme des cartes non ordonnées. Par conséquent, l’ordre de disposition d’un objet ne doit pas nécessairement correspondre à la même séquence binaire en C++.
glz::object
(types mixtes au moment de la compilation)std::map
std::unordered_map
std::pair
(active les clés dynamiques dans le stockage de la pile)
std::pair
est géré comme un objet avec une clé et une valeur uniques, mais lorsquestd::pair
est utilisé dans un tableau, Glaze concatène les paires en un seul objet.std::vector<std::pair<...>>
sera sérialisé en tant qu'objet unique. Si vous ne souhaitez pas ce comportement, définissez l'option de compilation.concatenate = false
.
std::variant
Voir Gestion des variantes pour plus d’informations.
std::unique_ptr
std::shared_ptr
std::optional
Les types nullables peuvent être alloués par une entrée valide ou annulés par le mot-clé 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));
Par défaut, les énumérations seront écrites et lues sous forme entière. Aucun glz::meta
n'est nécessaire si tel est le comportement souhaité.
Cependant, si vous préférez utiliser des énumérations comme chaînes dans JSON, elles peuvent être enregistrées dans glz::meta
comme suit :
enum class Color { Red, Green, Blue };
template <>
struct glz ::meta<Color> {
using enum Color;
static constexpr auto value = enumerate(Red,
Green,
Blue
);
};
Utilisé:
Color color = Color::Red;
std::string buffer{};
glz::write_json (color, buffer);
expect (buffer == " " Red " " );
Les commentaires sont pris en charge avec la spécification définie ici : JSONC
La prise en charge de la lecture des commentaires est fournie avec glz::read_jsonc
ou glz::read<glz::opts{.comments = true}>(...)
.
Le JSON formaté peut être écrit directement via une option de compilation :
auto ec = glz::write<glz::opts{. prettify = true }>(obj, buffer);
Ou bien, le texte JSON peut être formaté avec la fonction 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
est maintenant :
{
"i" : 287 ,
"d" : 3.14 ,
"hello" : " Hello World " ,
"arr" : [
1 ,
2 ,
3
]
}
Pour écrire du JSON minifié :
auto ec = glz::write_json(obj, buffer); // default is minified
Pour réduire l'appel de texte JSON :
std::string minified = glz::minify_json(buffer);
Si vous souhaitez exiger un JSON minifié ou si vous savez que votre entrée sera toujours minifiée, vous pouvez alors gagner un peu plus de performances en utilisant l'option de compilation .minified = true
.
auto ec = glz::read<glz::opts{. minified = true }>(obj, buffer);
Glaze prend en charge l'enregistrement d'un ensemble d'indicateurs booléens qui se comportent comme un tableau d'options de chaîne :
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);
};
Exemple:
flags_t s{};
expect (glz::write_json(s) == R"([ " x " , " z " ])");
Seuls "x"
et "z"
sont écrits car ils sont vrais. La lecture dans le tampon définira les booléens appropriés.
Lors de l'écriture de BEVE,
flags
n'utilisent qu'un seul bit par booléen (aligné sur les octets).
Parfois, vous souhaitez simplement écrire des structures JSON à la volée aussi efficacement que possible. Glaze fournit des structures de type tuple qui vous permettent d'empiler des structures d'allocation pour écrire du JSON à grande vitesse. Ces structures sont nommées glz::obj
pour les objets et glz::arr
pour les tableaux.
Vous trouverez ci-dessous un exemple de construction d'un objet, qui contient également un tableau, et de son écriture.
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]} )" );
Cette approche est nettement plus rapide que
glz::json_t
pour le JSON générique. Mais cela peut ne pas convenir à tous les contextes.
glz::merge
permet à l'utilisateur de fusionner plusieurs types d'objets JSON en un seul objet.
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
stocke les références aux lvalues pour éviter les copies
Voir JSON générique pour 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 écrit à peu près aussi rapidement dans un std::string
que dans un tampon de caractères brut. Si vous disposez de suffisamment d'espace alloué dans votre tampon, vous pouvez écrire dans le tampon brut, comme indiqué ci-dessous, mais ce n'est pas recommandé.
glz::read_json(obj, buffer);
const auto n = glz::write_json(obj, buffer.data()).value_or(0);
buffer.resize(n);
La structure glz::opts
définit les paramètres facultatifs au moment de la compilation pour la lecture/écriture.
Au lieu d'appeler glz::read_json(...)
, vous pouvez appeler glz::read<glz::opts{}>(...)
et personnaliser les options.
Par exemple : glz::read<glz::opts{.error_on_unknown_keys = false}>(...)
désactivera les erreurs sur les clés inconnues et ignorera simplement les éléments.
glz::opts
peut également basculer entre les formats :
glz::read<glz::opts{.format = glz::BEVE}>(...)
-> glz::read_beve(...)
glz::read<glz::opts{.format = glz::JSON}>(...)
-> glz::read_json(...)
La structure ci-dessous montre les options disponibles et le comportement par défaut.
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)
};
Beaucoup de ces options de compilation ont des wrappers pour appliquer l'option à un seul champ. Voir Wrappers pour plus de détails.
Par défaut Glaze est strictement conforme au dernier standard JSON sauf dans deux cas avec options associées :
validate_skipped
Cette option effectue une validation JSON complète pour les valeurs ignorées lors de l'analyse. Ceci n'est pas défini par défaut car les valeurs sont généralement ignorées lorsque l'utilisateur ne s'en soucie pas, et Glaze valide toujours les problèmes majeurs. Mais cela rend le saut plus rapide en ne se souciant pas de savoir si les valeurs ignorées sont exactement conformes à JSON. Par exemple, par défaut, Glaze garantira que les nombres ignorés contiennent tous les caractères numériques valides, mais il ne validera pas les problèmes tels que les zéros non significatifs dans les nombres ignorés, sauf si validate_skipped
est activé. Partout où Glaze analyse une valeur à utiliser, elle est entièrement validée.validate_trailing_whitespace
Cette option valide les espaces de fin dans un document analysé. Étant donné que Glaze analyse les structures C++, il n'est généralement pas nécessaire de poursuivre l'analyse une fois l'objet d'intérêt lu. Activez cette option si vous souhaitez vous assurer que le reste du document comporte des espaces valides, sinon Glaze ignorera simplement le contenu une fois le contenu qui vous intéresse analysé. Note
Glaze n'unicode pas automatiquement les caractères de contrôle d'échappement (par exemple "x1f"
à "u001f"
), car cela présente un risque d'incorporation de caractères nuls et d'autres caractères invisibles dans les chaînes. Une option de compilation sera ajoutée pour activer ces conversions (problème ouvert : écriture avec échappement Unicode), mais ce ne sera pas le comportement par défaut.
Il peut être utile de reconnaître l'existence d'une clé dans un objet pour éviter les erreurs, et pourtant la valeur peut ne pas être nécessaire ou exister en C++. Ces cas sont traités en enregistrant un type glz::skip
avec les métadonnées.
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 conçu pour aider à créer des API génériques. Parfois, une valeur doit être exposée à l'API, mais il n'est pas souhaitable de lire ou d'écrire la valeur en JSON. C'est le cas d'utilisation de glz::hide
.
glz::hide
masque la valeur de la sortie JSON tout en autorisant l'accès à l'API (et au pointeur 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
Vous pouvez analyser les numéros JSON cités directement en types tels que double
, int
, etc. en utilisant le wrapper 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 " ]
}
Les numéros JSON cités seront analysés directement dans le double
et std::vector<uint32_t>
. La fonction glz::quoted
fonctionne également pour les objets imbriqués et les tableaux.
Glaze prend en charge les lignes JSON (ou Newline Delimited JSON) pour les types de type tableau (par exemple std::vector
et 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);
Voir le répertoire ext
pour les extensions.
Glaze est distribué sous licence MIT avec une exception pour les formulaires intégrés :
--- Exception facultative à la licence ---
À titre d'exception, si, à la suite de la compilation de votre code source, des parties de ce logiciel sont intégrées dans une forme objet exécutable par machine de ce code source, vous pouvez redistribuer ces parties intégrées sous cette forme objet sans inclure les droits d'auteur et l'autorisation. remarques.