Die JSON-Link-Bibliothek ist eine leistungsstarke C++-JSON-Bibliothek ohne Zuweisung, die Folgendes unterstützt:
Die Bibliothek unterstützt andere Parsing-Modi, die auch gemischt werden können.
json_array_iterator
oder json_array_range
verwendet werden.json_value
-Typ, der die Iteration/verzögerte Analyse des Dokuments ermöglichtEinige andere bemerkenswerte Funktionen sind:
boost::multiprecision::cpp_int
oder GNU BigNum/Rational mpq_t
analysierenDie Bibliothek verwendet die BSL-Lizenz
Wenn die Struktur des JSON-Dokuments bekannt ist, sieht die Analyse wie folgt aus:
MyThing thing = daw::json::from_json<MyThing>( json_string );
oder für Array-Dokumente, bei denen das Stammverzeichnis des Dokuments ein Array ist, gibt es eine Hilfsmethode zur Vereinfachung, die wie folgt geparst werden kann:
std::vector<MyThing> things = daw::json::from_json_array<MyThing>( json_string2 );
Wenn die Struktur des JSON-Dokuments unbekannt ist, kann man einen json_value
erstellen, der als Ansicht fungiert und bei Bedarf Iteration und Pull-Analyse ermöglicht. Das Folgende ist ein Beispiel für das Öffnen eines json_value
aus JSON-Daten:
json_value val = daw::json::json_value( json_string );
Die Methoden from_json
und to_json
ermöglichen den Zugriff auf die meisten Parsing- und Serialisierungsanforderungen.
Der ereignisbasierte Parser (SAX) kann über daw::json::json_event_parser
aufgerufen werden. Es benötigt zwei Argumente, ein JSON-Dokument und einen Event-Handler. Der Ereignishandler kann sich für Ereignisse entscheiden, indem er eines der folgenden Mitglieder hat:
Die Zuordnung Ihrer Klassen zu JSON-Dokumenten erfolgt durch Spezialisierung des Merkmals daw::json::json_data_contract
. Eine zugeordnete Klasse muss nicht erneut zugeordnet werden, wenn sie Mitglied einer anderen zugeordneten Klasse ist. Das Merkmal json_data_contract
besteht aus zwei Teilen: Erstens handelt es sich um einen Typalias mit dem Namen type
, der die JSON-Mitglieder dem Konstruktor unserer Klasse zuordnet. Dadurch wird der Bedarf eines privaten Zugriffs auf die Klasse umgangen, vorausgesetzt, dass die Daten, die wir serialisieren würden, auch zum Aufbau der Klasse benötigt würden. Zum Beispiel:
struct Thing {
int a;
int b;
};
Das Konstrukt für Thing
erfordert 2 Ganzzahlen und wenn wir den folgenden JSON hätten:
{
"a" : 42 ,
"b" : 1234
}
Wir könnten die Zuordnung wie folgt durchführen:
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 >
>;
};
}
Dies besagt, dass die JSON-Klasse im Dokument mindestens zwei Mitglieder „a“ und „b“ hat, bei denen es sich um Ganzzahlen handelt. Sie werden an den Konstruktor von Thing
übergeben, wenn daw::json::from_json<Thing>( json_doc );
aufgerufen wird oder dass eine andere Klasse eine json_class<MemberName, Thing>
-Memberzuordnung hat. Das Obige ist die C++17-Zuordnungsmethode für die Namen, sie funktioniert auch in zukünftigen C++-Versionen. In C++20 und höher können die Namen jedoch in der Zuordnung integriert sein, z. B. json_number<"a", int>
. Das Obige ist alles, was zum Parsen von JSON benötigt wird, zum Serialisieren ist eine statische Memberfunktion im Merkmal erforderlich. Wenn wir das vorherige Beispiel nehmen und es erweitern, könnten wir Thing
wie folgt serialisieren:
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 );
}
}
Die Reihenfolge der als Tupel zurückgegebenen Mitglieder muss mit der Zuordnung im type
übereinstimmen. Dies ermöglicht auch die Übergabe des Ergebnisses von Zugriffsmethoden, wenn die Datenelemente nicht öffentlich sind. Außerdem muss die Klasse Thing
aus int, int
konstruierbar sein. Die Bibliothek unterstützt sowohl reguläre Konstruktoren als auch Aggregat-Init ( Thing{ int, int }
und Thing( int, int )
) in C++17.
to_json_data
muss kein Tupel von Verweisen auf die vorhandenen Objektmitglieder zurückgeben, kann aber auch berechnete Werte zurückgeben. R-Werte werden nicht durchgelassen, da es sich häufig um temporäre Werte handelt, was zu einer Debugging-Entfernung über große Entfernungen führen kann. Die Bibliothek führt dazu static_assert aus und schlägt vor, <daw/daw_tuple_forward.h>
einzuschließen und daw::forward_nonrvalue_as_tuple( ... )
aufzurufen, um temporäre Dateien zu speichern und andere Referenztypen weiterzuleiten. Die Parser arbeiten, indem sie jedes Argument an Ort und Stelle im Aufruf des Konstruktors der Klasse konstruieren. Die einzelnen Argumentparser können auf die angegebenen Umstände der Daten abgestimmt werden (z. B. Gleitkomma- und Ganzzahlzahlen). Wenn dann unser Typmerkmal die zum Aufbau der C++-Klasse erforderlichen Argumente und deren Reihenfolge definiert, können wir uns jedes Mitglied im JSON ansehen. Jetzt konstruieren wir den Wert mit dem Ergebnis jedes Parsers; Ähnlich wie T{ parse<0, json_string<"name">>( data ), parse<1, json_number<"age", unsigned>>( data ), parse<json_number<2, "number>>( data )}
Für jedes Mitglied wird der Datenstrom vorwärts verschoben, bis wir das Mitglied finden, das wir analysieren müssen, wobei interessierte Speicherorte für die spätere Analyse gespeichert werden. Dieser Prozess ermöglicht es uns, auch andere Klassen als Mitglieder zu analysieren json_class<"member_name", Type>
Zuordnungstyp Damit sich jedes Zuordnungsmerkmal nur mit seinen spezifischen Mitgliedern und nicht mit deren Details befassen muss.
In unbenannten Kontexten wie dem Stammwert, Array-Elementen, einigen Schlüsselwerttypen und Variantenelementlisten, bei denen der Name no_name
wäre, können anstelle der JSON-Zuordnungstypen einige native C++-Datentypen verwendet werden. Dazu gehören Ganzzahl, Gleitkomma, Bool, std::string, std::string_view, assoziative Container, Sequenzcontainer, Nullable/Optional-ähnliche Typen und zuvor zugeordnete Klassen.
Zum Beispiel, um ein Array von Zeichenfolgen abzubilden.
template <>
struct daw ::json::json_data_contract<MyType> {
using type = json_member_list<json_array< " member_name " , std::string>>;
};
Mit vcpkg kann man sich die neueste Version holen, der Port heißt daw-json-link
find_package ( daw-json-link )
#...
target_link_libraries ( MyTarget daw::daw-json-link )
Die Bibliothek ist nur ein Header und kann zusammen mit ihren beiden Abhängigkeiten geklont werden. Anschließend werden jeweils die include/
Unterordner zum Include-Pfad des Compilers hinzugefügt
Um daw_json_link in Ihren cmake-Projekten zu verwenden, sollte das Hinzufügen von Folgendem ermöglichen, es zusammen mit den Abhängigkeiten einzubinden:
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 )
Auf einem System mit Bash ist es ähnlich, auch auf anderen Systemen kann Folgendes für das System installiert werden
git clone https://github.com/beached/daw_json_link
cd daw_json_link
mkdir build
cd build
cmake ..
cmake --install .
Dies ermöglicht die Installation von cmake find_package oder die Verwendung als regulären Header, solange der Include-Ordner des Installationspräfixes in den Include-Pfaden des Compilers enthalten ist
Im Folgenden werden die Tests erstellt und ausgeführt.
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 .
Nach dem Aufbau können dort auch die einzelnen Exemplare getestet werden. city_test_bin
erfordert den Pfad zur JSON-Datei der Städte.
./tests/city_test_bin ../test_data/cities.json
Die Reihenfolge der Mitglieder in den Datenstrukturen sollte nach Möglichkeit grundsätzlich mit der der JSON-Daten übereinstimmen. Der Parser ist schneller, wenn er nicht nach Werten suchen muss. Wenn optionale Werte in den JSON-Daten fehlen, kann dies die Analyse ebenfalls verlangsamen. Wenn möglich, lassen Sie sie als Null senden. Der Parser ordnet nicht zu. Die analysierten Datentypen können verwendet werden, und dies ermöglicht die Verwendung benutzerdefinierter Allokatoren oder einer Mischung, da deren Datenstrukturen die Zuweisung übernehmen. Standardmäßig wird für Arrays der std::vector verwendet. Wenn dies nicht erwünscht ist, müssen Sie den Typ angeben.
Die Bibliothek deaktiviert bzw. maskiert derzeit bei der Serialisierung die Mitgliedsnamen nicht. Es wird erwartet, dass sie gültig und ohne Escapezeichen sind. Dies kann eine zukünftige optionale Ergänzung sein, da hierfür Kosten anfallen.
Es gibt geringfügige Unterschiede zwischen C++17 und C++20, wobei C++20 einige Codes zulässt, die in C++17 nicht verfügbar sind.
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>>;
};
}
Beide Versionen von C++ unterstützen diese Methode zum Benennen von Mitgliedern.
Bei der Kompilierung innerhalb des C++20-Compilers können die Mitgliedsnamen zusätzlich zur Übergabe eines char const *
wie in C++17 direkt als Zeichenfolgenliterale angegeben werden. Die Unterstützung des C++20-Compilers ist noch sehr früh und es gibt Drachen. Es gibt bekannte Probleme mit g++9.x im C++20-Modus und es wurde nur mit g++10/11 getestet. Hier sind Drachen
namespace daw ::json {
template <>
struct json_data_contract <MyType> {
using type = json_member_list<json_number< " member_name " >>;
};
}
Sobald ein Datentyp einem json_data_contract
zugeordnet wurde, stellt die Bibliothek Methoden zum Parsen von JSON für ihn bereit
MyClass my_class = from_json<MyClass>( json_str );
Wenn die Eingabe vertrauenswürdig ist, kann alternativ die weniger überprüfte Version schneller sein
MyClass my_class = from_json<MyClass, options::parse_flags<options::CheckedParseMode::no>>( json_str );
JSON-Dokumente mit Array-Roots verwenden zum Parsen die Funktion from_json_array
std::vector<MyClass> my_data = from_json_array<MyClass>( json_str );
Wenn die Eingabe vertrauenswürdig ist, kann alternativ die weniger überprüfte Version schneller sein
std::vector<MyClass> my_data = from_json_array<MyClass, std::vector<MyClass>, options::parse_flags<options::CheckedParseMode::no>>( json_str );
json_array_iterator
Wenn Sie mit JSON-Array-Daten arbeiten möchten, können Sie einen Iterator erhalten und die Standardalgorithmen verwenden. Die Iteration über Arrays in JSON-Daten kann über den json_array_iterator
erfolgen
using iterator_t = json_array_iterator<MyClass>;
auto pos = std::find( iterator_t ( json_str ), iterator_t ( ), MyClass( ... ) );
Wenn die Eingabe vertrauenswürdig ist, können Sie alternativ die weniger überprüfte Version aufrufen
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
Für ein DOM wie API, das oft für Dinge wie GUIs und die Bereitstellung von Code verwendet wird, wenn die Zuordnungen unzureichend sind, kann man json_value
verwenden. Dies wird im json_to_cpp-Tool verwendet.
auto jv = daw::json::json_value( json_doc );
Man kann einen JSON-Pfad verwenden, um eine Ganzzahl zu extrahieren
int foo = as< int >( jv[ " path.to.int " ] );
Hier ist "path.to.int"
ein JSON-Pfad, der das Drilling in eine JSON-Klasse wie z. B. darstellt
{
"path" : {
"to" : {
"int" : 5
}
}
}
Man kann auch über eine Array-ähnliche Syntax im JSON-Pfad auswählen, "path[5]"
würde das 5. Element/Mitglied von "path"
auswählen. Wenn Sie in JSON serialisieren möchten. Die JSON-Pfad-Syntax funktioniert auch mit from_json
, from_json_array
und json_array_iterator
.
to_json
std::string my_json_data = to_json( MyClass{} );
Oder serialisieren Sie ein Array, eine Sammlung, einen Bereich oder eine Ansicht von Dingen. Erfordert nur std::begin(...)
und std::end(...)
um für den Typ zu funktionieren. Dies ermöglicht die Serialisierung, wenn der Typ keine konstruierbare Sammlung von Dingen ist.
std::vector<MyClass> arry = ...;
std::string my_json_data = to_json_array( arry );
Beim Parsen von Fehlern wird standardmäßig eine daw::json::json_exception
ausgelöst, die Informationen über den Grund und den Ort des Fehlers enthält.
Wenn Ausnahmen deaktiviert sind, ruft die Bibliothek standardmäßig std::terminate
bei einem Analysefehler auf.
Während die Fehlerbehandlung standardmäßig eine daw::json::json_exception
bei Fehlern auslöst oder std::terminate
aufruft, wenn Ausnahmen deaktiviert sind. Dieses Verhalten kann man ändern, indem man den Funktionszeiger daw::json::daw_json_error_handler
setzt. Die einzige Voraussetzung ist, dass die Funktion nicht zurückkehrt. Ein Beispiel, das dies nutzt, ist in error_handling_bench_test.cpp
Die Fehlerprüfung kann pro Analyse geändert werden. from_json
, from_json_array
, json_value
, json_array_iterator
und ähnliche unterstützen alle Parsing-Optionen. Für Aufrufe kann eine Parser-Option bereitgestellt werden. Die verfügbaren Optionen sind im Kochbuchelement parser_policies dokumentiert.
daw::json::json_exception
hat eine Mitgliedsfunktion std::string_view reason( ) const
std::exception
's what( )
ähnelt, aber einen std::string
mit mehr Kontext zurückgibt als what( )
. Wenn Sie Ausnahmen in einer Umgebung deaktivieren möchten, in der sie vorhanden sind, können Sie DAW_JSON_DONT_USE_EXCEPTIONS
definieren, um das Auslösen von Ausnahmen durch die Bibliothek zu deaktivieren, oder den Handler festlegen. Dies wird nicht mehr empfohlen, da der Handler auf einen der beiden Standardwerte daw::json::default_error_handling_throwing
festgelegt werden kann daw::json::default_error_handling_throwing
oder daw::json::default_error_handling_terminating
.
Dies kann erreicht werden, indem eine Spezialisierung von json_data_contract
in den Namespace daw::json
geschrieben wird. Zum Beispiel:
# 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);
}
Siehe im Compiler Explorer
Es werden sowohl Aggregat- als auch Benutzerkonstruktoren unterstützt. Die Beschreibung enthält die Werte, die zum Erstellen Ihres Typs und der Reihenfolge erforderlich sind. Die angegebene Reihenfolge ist die Reihenfolge, in der sie im Konstruktor platziert werden. Es gibt auch Anpassungspunkte, mit denen Sie Ihren Typ erstellen können. Eine Klasse wie:
# 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 " >
>;
};
}
Funktioniert auch. Das Gleiche, aber 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>
>;
};
}
Die Klassenbeschreibungen sind mit ihren Untermitgliedern rekursiv. Mit der vorherigen AggClass
kann man sie als Mitglied einer anderen Klasse einbinden
// 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>
>;
};
}
Das Obige ordnet eine Klasse MyClass
zu, die eine andere Klasse hat, die als AggClass beschrieben wird. Außerdem können Sie sehen, dass die Mitgliedsnamen der C++-Klasse nicht mit denen der zugeordneten JSON-Namen übereinstimmen müssen und dass Zeichenfolgen std::string_view
als Ergebnistyp verwenden können. Dies ist eine wichtige Leistungsverbesserung, wenn Sie garantieren können, dass der Puffer mit der JSON-Datei so lange vorhanden ist wie die Klasse.
Iterieren über JSON-Arrays. Der Eingabeiterator daw::json::json_array_iterator<JsonElement>
ermöglicht einen Iterator über das Array von JSON-Elementen. Technisch gesehen handelt es sich um einen Eingabeiterator, der jedoch wie ein Vorwärtsiterator gespeichert und wiederverwendet werden kann. Es wird keine Referenz, sondern ein Wert zurückgegeben.
# 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 " ;
}
}
Das Parsen kann bei einem bestimmten Mitglied oder Element beginnen. Ein optionaler Mitgliedspfad zu from_json
, from_json_array
, json_value
, json_array_iterator
und ähnlichem kann angegeben werden. Das Format ist eine durch Punkte getrennte Liste von Mitgliedsnamen und optional ein Array-Index wie member0.member1
, was einer Analyse von Folgendem entspricht:
{
"member0" : {
"member1" : {}
}
}
oder member0[5].member1
wodurch die Analyse bei „member1“ in einem Dokument wie dem folgenden beginnen würde:
{
"member0" : [
" a " ,
" b " ,
" c " ,
" d " ,
" e " ,
{
"member1" : " "
}
]
}
oder
{
"member0" : {
"a" : " " ,
"b" : " " ,
"c" : " " ,
"d" : " " ,
"e" : " " ,
"f" : {
"member1" : " "
}
}
}
Kommentare werden unterstützt, wenn die Parser-Richtlinie für sie verwendet wird. Derzeit gibt es zwei Formen von Kommentarrichtlinien.
//
Zeilenkommentare und C-Stil /* */
Kommentare. { // This is a comment
"a" /*this is also a comment*/: "a's value"
}
#
-Zeilenkommentare im Hash-Stil { # This is a comment
"a" #this is also a comment
: "a's value"
}
Die Kommentarrichtlinie kann über PolicyCommentTypes
festgelegt werden. Weitere Informationen finden Sie unter parser_policies.
Um die Serialisierung zu ermöglichen, muss in Ihrer Spezialisierung von json_data_contract
eine zusätzliche statische Funktion namens to_json_data( Thing const & );
das gibt ein Tupel von Mitgliedern zurück. Es stellt eine Zuordnung Ihres Typs zu den in der Klassenbeschreibung bereitgestellten Argumenten bereit. Um in einen JSON-String zu serialisieren, ruft man to_json( my_thing );
auf. Dabei ist my_thing
ein registrierter Typ oder einer der Grundtypen wie Container, Maps, Strings, Bool und Numbers. Das Ergebnis der statischen Methode to_json_data( Thing const & )
ist ein tuple
, dessen Elemente in der Reihenfolge im zugehörigen type
vom Typ json_data_contract
übereinstimmen. Aufgrund der Art und Weise, wie die Methode verwendet wird, führen Tupel mit R-Wert-Elementen zu einem Fehler bei der Verwendung nach der Zerstörung. Der Compiler gibt in diesem Fall einen Fehler aus. Wenn Sie stattdessen <daw/daw_tuple_forward.h>
und die Methode daw::forward_nonrvalue_as_tuple
einbinden, werden die R-Werte gespeichert, anstatt sie als Referenz zu übergeben. Oft ist es das Ergebnis berechneter Tupelelemente. Anhand des obigen Beispiels können wir eine to_json_data
-Methode hinzufügen
# 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 );
Alternativ kann die Ausgabe an einen beliebigen WritableOutput-Typ erfolgen. Standardmäßig umfasst dies FILE*, iostreams, Zeichencontainer und Zeichenzeiger. Im json_data_constract
Ihres Typs. Oder wenn Sie sich dafür entscheiden, können Sie einen ostream-Operator<< für seinen Typ erhalten, der den JSON in den Ausgabestream einfügt, indem Sie einen Typalias mit dem Namen opt_into_iostreams
hinzufügen (der Typ, den er aliasisiert, spielt keine Rolle) und daw/json/daw_json_iostream.h
einschließen . Zum Beispiel
# 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 ' ;
Ein funktionierendes Beispiel finden Sie unter daw_json_iostream_test.cpp oder im Compiler-Explorer
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>
Es gibt einige Definitionen, die sich auf die Funktionsweise von JSON Link auswirken
DAW_JSON_DONT_USE_EXCEPTIONS
– Steuert, ob Ausnahmen zulässig sind. Ist dies nicht der Fall, wird bei Fehlern ein std::terminate()
angezeigt. Dies geschieht automatisch, wenn Ausnahmen deaktiviert sind (z. B. -fno-exceptions
).DAW_ALLOW_SSE42
– Erlaubt den experimentellen SSE42-Modus, im Allgemeinen ist der constexpr-Modus schnellerDAW_JSON_NO_CONST_EXPR
– Dies kann verwendet werden, um zu ermöglichen, dass Klassen ohne spezielle Elemente zum Verschieben/Kopieren aus JSON-Daten vor C++ 20 erstellt werden. Dieser Modus funktioniert nicht in einem konstanten Ausdruck vor C++ 20, wenn dieses Flag nicht mehr benötigt wird. Ältere Compiler funktionieren möglicherweise noch, aber beim Testen führten einige aufgrund fehlerhafter C++17-Unterstützung zu ICE- oder Kompilierungsfehlern. Oft kann es auch hilfreich sein, constexpr nicht zu verwenden.
json_key_value
kann sichergestellt werden, dass beide analysiert oder sortiert werden können.std::multimap<std::string, T>
oder std::vector<std::pair<std::string, T>>
werden alle Mitglieder in der Reihenfolge mit ersterem beibehalten. Alternativ ermöglicht der Typ json_value
die Iteration über die Klassenmitglieder und das verzögerte Parsen des richtigen Mitglieds. Siehe Cookbook Key Values, in dem diese Methoden demonstriert werden.