jsoncons ist eine reine C++-Header-Bibliothek zum Erstellen von JSON und JSON-ähnlichen Datenformaten wie CBOR. Für jedes unterstützte Datenformat können Sie auf verschiedene Arten mit den Daten arbeiten:
Als variantenartige, allokatorbewusste Datenstruktur, basic_json
Als stark typisierte C++-Datenstruktur, die json_type_traits implementiert
Mit Zugriff auf Cursorebene auf einen Strom von Parse-Ereignissen, etwas analog zum StAX-Pull-Parsing und Push-Serialisierung in der XML-Welt.
Im Vergleich zu anderen JSON-Bibliotheken wurde jsoncons für die Verarbeitung sehr großer JSON-Texte entwickelt. Das Herzstück sind Parser und Serialisierer im SAX-Stil. Es unterstützt das Lesen eines gesamten JSON-Textes im Speicher in einer variantenähnlichen Struktur. Es unterstützt aber auch den effizienten Zugriff auf die zugrunde liegenden Daten durch Pull-Parsing und Push-Serialisierung im StAX-Stil. Und es unterstützt das inkrementelle Parsen in die bevorzugte Form eines Benutzers unter Verwendung von Informationen über Benutzertypen, die durch Spezialisierungen von json_type_traits bereitgestellt werden.
Das jsoncons-Datenmodell unterstützt die bekannten JSON-Typen – Nullen, Boolesche Werte, Zahlen, Strings, Arrays, Objekte – sowie Byte-Strings. Darüber hinaus unterstützt jsoncons die semantische Kennzeichnung von Datums- und Uhrzeitangaben, Epochenzeiten, großen Ganzzahlen, großen Dezimalzahlen, großen Gleitkommazahlen und binären Kodierungen. Dies ermöglicht es, diese Typsemantik beim Parsen von JSON-ähnlichen Datenformaten wie CBOR, die sie enthalten, beizubehalten.
jsoncons wird unter der Boost-Softwarelizenz vertrieben.
jsoncons ist kostenlos, freut sich aber über Unterstützung, um seine Entwicklung aufrechtzuerhalten. Wenn Sie diese Bibliothek hilfreich finden, denken Sie bitte darüber nach, eine einmalige Spende zu leisten oder ein ❤️-Sponsor zu werden.
Im Zuge der Weiterentwicklung der jsoncons
-Bibliothek haben sich manchmal Namen geändert. Um den Übergang zu erleichtern, lehnt jsoncons die alten Namen ab, unterstützt jedoch weiterhin viele davon. Die veralteten Namen können durch die Definition des Makros JSONCONS_NO_DEPRECATED
unterdrückt werden. Dies wird für neuen Code empfohlen.
„Apache Kvrocks nutzt konsequent Jsoncons, um Benutzern Unterstützung für JSON-Datenstrukturen zu bieten. Wir finden die Entwicklungserfahrung mit JSONCons hervorragend!“
„Ich habe Ihre Bibliothek in meiner Muttersprache – R – verwendet und ein R-Paket erstellt, das es (a) JMESpath- und JSONpath-Abfragen auf JSON-Strings oder R-Objekten erleichtert und (b) anderen R-Entwicklern die Verknüpfung mit Ihrer Bibliothek erleichtert ."
„Ich verwende Ihre Bibliothek als externe Schnittstelle zum Übergeben von Daten und verwende außerdem die Konvertierungen von CSV nach JSON, die beim Konvertieren von Daten für die Verwendung in Javascript sehr hilfreich sind.“
„Überprüft, dass es für meine Anforderungen in JSON und CBOR perfekt funktioniert.“
„Die JSONPath-Funktion dieser Bibliothek ist großartig“
„Wir nutzen die JMESPath-Implementierung ziemlich häufig.“
„Wir lieben Ihren JSON-Schema-Validator. Wir verwenden ihn in ER/Studio, unserem Datenmodellierungstool, um JSON-Schemadateien zu analysieren, damit wir daraus Entitätsbeziehungsmodelle erstellen können.“
„Die Serialisierungsbibliothek der Wahl mit ihren schönen Zuordnungen und ihrer Benutzerfreundlichkeit“
„Wirklich gut“ „Tolles Projekt“ „ Sehr solide und sehr zuverlässig“ „Mein Team liebt es“ „Ihr Repo ist der Hammer!!!!“
Beginnen Sie mit HealthImaging-Bildsätzen und Bildrahmen mithilfe eines AWS SDK
RubyGems.org rjsoncons Coppelia Robotics CSPro-Lizenzen
Sie können den vcpkg-Plattformbibliotheksmanager verwenden, um das jsoncons-Paket zu installieren.
Oder laden Sie die neueste Version herunter und entpacken Sie die ZIP-Datei. Kopieren Sie das Verzeichnis include/jsoncons
in Ihr include
-Verzeichnis. Wenn Sie Erweiterungen verwenden möchten, kopieren Sie auch include/jsoncons_ext
.
Oder laden Sie den neuesten Code auf main herunter.
Die Bibliothek erfordert einen C++-Compiler mit C++11-Unterstützung. Darüber hinaus definiert die Bibliothek jsoncons::endian
, jsoncons::basic_string_view
, jsoncons::optional
und jsoncons::span
, die bei Erkennung auf ihre Standardbibliotheksäquivalente typisiert werden. Andernfalls werden sie in interne, C++11-kompatible Implementierungen typdefiniert.
Die Bibliothek verwendet Ausnahmen und in einigen Fällen std::error_codes, um Fehler zu melden. Abgesehen von jsoncons::assertion_error
implementieren alle jsoncons-Ausnahmeklassen die jsoncons::json_error-Schnittstelle. Wenn Ausnahmen deaktiviert sind oder das Kompilierzeitmakro JSONCONS_NO_EXCEPTIONS
definiert ist, werden Auswürfe zu Aufrufen von std::terminate
.
json_benchmarks bietet einige Messungen zum Vergleich von jsoncons
mit anderen json
-Bibliotheken.
JSONTestSuite- und JSON_checker-Testsuiten
Leistungsbenchmarks mit Text und Ganzzahlen
Leistungsbenchmarks mit Text und Doubles
Der JSONPath-Vergleich zeigt, wie Jsoncons JsonPath im Vergleich zu anderen Implementierungen abschneidet
Arbeiten mit JSON-Daten
Arbeiten mit CBOR-Daten
Für die folgenden Beispiele müssen Sie einige Header-Dateien einschließen und eine Zeichenfolge mit JSON-Daten initialisieren:
# include < jsoncons/json.hpp >
# include < jsoncons_ext/jsonpath/jsonpath.hpp >
# include < iostream >
using namespace jsoncons ; // for convenience
std::string data = R"(
{
"application": "hiking",
"reputons": [
{
"rater": "HikingAsylum",
"assertion": "advanced",
"rated": "Marilyn C",
"rating": 0.90,
"generated": 1514862245
}
]
}
)" ;
Mit jsoncons können Sie auf verschiedene Arten mit den Daten arbeiten:
Als variantenartige Datenstruktur basic_json
Als stark typisierte C++-Datenstruktur, die json_type_traits implementiert
Mit Zugriff auf Cursorebene auf einen Stream von Analyseereignissen
int main ()
{
// Parse the string of data into a json value
json j = json::parse (data);
// Does object member reputons exist?
std::cout << " (1) " << std::boolalpha << j. contains ( " reputons " ) << " nn " ;
// Get a reference to reputons array
const json& v = j[ " reputons " ];
// Iterate over reputons array
std::cout << " (2) n " ;
for ( const auto & item : v. array_range ())
{
// Access rated as string and rating as double
std::cout << item[ " rated " ]. as <std::string>() << " , " << item[ " rating " ]. as < double >() << " n " ;
}
std::cout << " n " ;
// Select all "rated" with JSONPath
std::cout << " (3) n " ;
json result = jsonpath::json_query (j, " $..rated " );
std::cout << pretty_print (result) << " nn " ;
// Serialize back to JSON
std::cout << " (4) n " << pretty_print (j) << " nn " ;
}
Ausgabe:
(1) true
(2)
Marilyn C, 0.9
(3)
[
"Marilyn C"
]
(4)
{
"application": "hiking",
"reputons": [
{
"assertion": "advanced",
"generated": 1514862245,
"rated": "Marilyn C",
"rater": "HikingAsylum",
"rating": 0.9
}
]
}
jsoncons unterstützt die Umwandlung von JSON-Texten in C++-Datenstrukturen. Die Funktionen decode_json und encode_json konvertieren Zeichenfolgen oder Streams von JSON-Daten in C++-Datenstrukturen und zurück. Dekodier- und Kodierungsarbeiten für alle C++-Klassen, für die json_type_traits definiert ist. jsoncons unterstützt bereits viele Typen in der Standardbibliothek, und Ihre eigenen Typen werden ebenfalls unterstützt, wenn Sie json_type_traits
im jsoncons
-Namespace spezialisieren.
namespace ns {
enum class hiking_experience {beginner,intermediate,advanced};
class hiking_reputon
{
std::string rater_;
hiking_experience assertion_;
std::string rated_;
double rating_;
std::optional<std::chrono::seconds> generated_; // assumes C++17, if not use jsoncons::optional
std::optional<std::chrono::seconds> expires_;
public:
hiking_reputon ( const std::string& rater,
hiking_experience assertion,
const std::string& rated,
double rating,
const std::optional<std::chrono::seconds>& generated =
std::optional<std::chrono::seconds>(),
const std::optional<std::chrono::seconds>& expires =
std::optional<std::chrono::seconds>())
: rater_(rater), assertion_(assertion), rated_(rated), rating_(rating),
generated_ (generated), expires_(expires)
{
}
const std::string& rater () const { return rater_;}
hiking_experience assertion () const { return assertion_;}
const std::string& rated () const { return rated_;}
double rating () const { return rating_;}
std::optional<std::chrono::seconds> generated () const { return generated_;}
std::optional<std::chrono::seconds> expires () const { return expires_;}
friend bool operator ==( const hiking_reputon& lhs, const hiking_reputon& rhs)
{
return lhs. rater_ == rhs. rater_ && lhs. assertion_ == rhs. assertion_ &&
lhs. rated_ == rhs. rated_ && lhs. rating_ == rhs. rating_ &&
lhs. confidence_ == rhs. confidence_ && lhs. expires_ == rhs. expires_ ;
}
friend bool operator !=( const hiking_reputon& lhs, const hiking_reputon& rhs)
{
return !(lhs == rhs);
};
};
class hiking_reputation
{
std::string application_;
std::vector<hiking_reputon> reputons_;
public:
hiking_reputation ( const std::string& application,
const std::vector<hiking_reputon>& reputons)
: application_(application),
reputons_ (reputons)
{}
const std::string& application () const { return application_;}
const std::vector<hiking_reputon>& reputons () const { return reputons_;}
};
} // namespace ns
// Declare the traits. Specify which data members need to be serialized.
JSONCONS_ENUM_TRAITS (ns::hiking_experience, beginner, intermediate, advanced)
// First four members listed are mandatory, generated and expires are optional
JSONCONS_N_CTOR_GETTER_TRAITS(ns::hiking_reputon, 4 , rater, assertion, rated, rating,
generated, expires)
// All members are mandatory
JSONCONS_ALL_CTOR_GETTER_TRAITS(ns::hiking_reputation, application, reputons)
int main()
{
// Decode the string of data into a c++ structure
ns::hiking_reputation v = decode_json<ns::hiking_reputation>(data);
// Iterate over reputons array value
std::cout << " (1) n " ;
for ( const auto & item : v. reputons ())
{
std::cout << item. rated () << " , " << item. rating ();
if (item. generated ())
{
std::cout << " , " << (*item. generated ()). count ();
}
std::cout << " n " ;
}
// Encode the c++ structure into a string
std::string s;
encode_json (v, s, indenting::indent);
std::cout << " (2) n " ;
std::cout << s << " n " ;
}
Ausgabe:
(1)
Marilyn C, 0.9, 1514862245
(2)
{
"application": "hiking",
"reputons": [
{
"assertion": "advanced",
"generated": 1514862245,
"rated": "Marilyn C",
"rater": "HikingAsylum",
"rating": 0.9
}
]
}
In diesem Beispiel werden die praktischen Makros JSONCONS_ENUM_TRAITS
, JSONCONS_N_CTOR_GETTER_TRAITS
und JSONCONS_ALL_CTOR_GETTER_TRAITS
verwendet, um die json_type_traits für den Enum-Typ ns::hiking_experience
, die Klasse ns::hiking_reputon
(mit einigen nicht obligatorischen Mitgliedern) und die Klasse zu spezialisieren ns::hiking_reputation
(mit allen obligatorischen Mitgliedern.) Das Makro JSONCONS_ENUM_TRAITS
generiert den Code aus den Enum-Bezeichnern, und die Makros JSONCONS_N_CTOR_GETTER_TRAITS
und JSONCONS_ALL_CTOR_GETTER_TRAITS
generieren den Code aus den Get-Funktionen und einem Konstruktor. Diese Makrodeklarationen müssen außerhalb aller Namespace-Blöcke platziert werden.
Weitere Möglichkeiten zur Spezialisierung json_type_traits
finden Sie in den Beispielen.
Eine typische Pull-Parsing-Anwendung verarbeitet das Ereignis current()
wiederholt und ruft next()
auf, um zum nächsten Ereignis zu gelangen, bis done()
true
zurückgibt.
int main ()
{
json_string_cursor cursor (data);
for (; !cursor. done (); cursor. next ())
{
const auto & event = cursor. current ();
switch (event. event_type ())
{
case staj_event_type::begin_array:
std::cout << event. event_type () << " " << " n " ;
break ;
case staj_event_type::end_array:
std::cout << event. event_type () << " " << " n " ;
break ;
case staj_event_type::begin_object:
std::cout << event. event_type () << " " << " n " ;
break ;
case staj_event_type::end_object:
std::cout << event. event_type () << " " << " n " ;
break ;
case staj_event_type::key:
// Or std::string_view, if supported
std::cout << event. event_type () << " : " << event. get <jsoncons::string_view>() << " n " ;
break ;
case staj_event_type::string_value:
// Or std::string_view, if supported
std::cout << event. event_type () << " : " << event. get <jsoncons::string_view>() << " n " ;
break ;
case staj_event_type::null_value:
std::cout << event. event_type () << " n " ;
break ;
case staj_event_type::bool_value:
std::cout << event. event_type () << " : " << std::boolalpha << event. get < bool >() << " n " ;
break ;
case staj_event_type::int64_value:
std::cout << event. event_type () << " : " << event. get < int64_t >() << " n " ;
break ;
case staj_event_type::uint64_value:
std::cout << event. event_type () << " : " << event. get < uint64_t >() << " n " ;
break ;
case staj_event_type::double_value:
std::cout << event. event_type () << " : " << event. get < double >() << " n " ;
break ;
default :
std::cout << " Unhandled event type: " << event. event_type () << " " << " n " ;
break ;
}
}
}
Ausgabe:
begin_object
key: application
string_value: hiking
key: reputons
begin_array
begin_object
key: rater
string_value: HikingAsylum
key: assertion
string_value: advanced
key: rated
string_value: Marilyn C
key: rating
double_value: 0.9
key: generated
uint64_value: 1514862245
end_object
end_array
end_object
Sie können mithilfe der Pipe-Syntax einen Filter auf einen Cursor anwenden (z. B. cursor | filter1 | filter2 | ...
).
int main ()
{
std::string name;
auto filter = [&]( const staj_event& ev, const ser_context&) -> bool
{
if (ev. event_type () == staj_event_type::key)
{
name = ev. get <std::string>();
return false ;
}
if (name == " rated " )
{
name. clear ();
return true ;
}
return false ;
};
json_string_cursor cursor (data);
auto filtered_c = cursor | filter;
for (; !filtered_c. done (); filtered_c. next ())
{
const auto & event = filtered_c. current ();
switch (event. event_type ())
{
case staj_event_type::string_value:
// Or std::string_view, if C++17
std::cout << event. event_type () << " : " << event. get <jsoncons::string_view>() << " n " ;
break ;
default :
std::cout << " Unhandled event type n " ;
break ;
}
}
}
Ausgabe:
Marilyn C
Für die folgenden Beispiele müssen Sie einige Header-Dateien einschließen und einen Puffer mit CBOR-Daten initialisieren:
# include < iomanip >
# include < iostream >
# include < jsoncons/json.hpp >
# include < jsoncons_ext/cbor/cbor.hpp >
# include < jsoncons_ext/jsonpath/jsonpath.hpp >
using namespace jsoncons ; // for convenience
const std::vector< uint8_t > data = {
0x9f , // Start indefinte length array
0x83 , // Array of length 3
0x63 , // String value of length 3
0x66 , 0x6f , 0x6f , // "foo"
0x44 , // Byte string value of length 4
0x50 , 0x75 , 0x73 , 0x73 , // 'P''u''s''s'
0xc5 , // Tag 5 (bigfloat)
0x82 , // Array of length 2
0x20 , // -1
0x03 , // 3
0x83 , // Another array of length 3
0x63 , // String value of length 3
0x62 , 0x61 , 0x72 , // "bar"
0xd6 , // Expected conversion to base64
0x44 , // Byte string value of length 4
0x50 , 0x75 , 0x73 , 0x73 , // 'P''u''s''s'
0xc4 , // Tag 4 (decimal fraction)
0x82 , // Array of length 2
0x38 , // Negative integer of length 1
0x1c , // -29
0xc2 , // Tag 2 (positive bignum)
0x4d , // Byte string value of length 13
0x01 , 0x8e , 0xe9 , 0x0f , 0xf6 , 0xc3 , 0x73 , 0xe0 , 0xee , 0x4e , 0x3f , 0x0a , 0xd2 ,
0xff // "break"
};
Mit jsoncons können Sie mit den CBOR-Daten ähnlich wie mit JSON-Daten arbeiten:
Als variantenartige Datenstruktur basic_json
Als stark typisierte C++-Datenstruktur, die json_type_traits implementiert
Mit Zugriff auf Cursorebene auf einen Stream von Analyseereignissen
int main ()
{
// Parse the CBOR data into a json value
json j = cbor::decode_cbor<json>(data);
// Pretty print
std::cout << " (1) n " << pretty_print (j) << " nn " ;
// Iterate over rows
std::cout << " (2) n " ;
for ( const auto & row : j. array_range ())
{
std::cout << row[ 1 ]. as <jsoncons::byte_string>() << " ( " << row[ 1 ]. tag () << " ) n " ;
}
std::cout << " n " ;
// Select the third column with JSONPath
std::cout << " (3) n " ;
json result = jsonpath::json_query (j, " $[*][2] " );
std::cout << pretty_print (result) << " nn " ;
// Serialize back to CBOR
std::vector< uint8_t > buffer;
cbor::encode_cbor (j, buffer);
std::cout << " (4) n " << byte_string_view (buffer) << " nn " ;
}
Ausgabe:
(1)
[
["foo", "UHVzcw", "0x3p-1"],
["bar", "UHVzcw==", "1.23456789012345678901234567890"]
]
(2)
50,75,73,73 (n/a)
50,75,73,73 (base64)
(3)
[
"0x3p-1",
"1.23456789012345678901234567890"
]
(4)
82,83,63,66,6f,6f,44,50,75,73,73,c5,82,20,03,83,63,62,61,72,d6,44,50,75,73,73,c4,82,38,1c,c2,4d,01,8e,e9,0f,f6,c3,73,e0,ee,4e,3f,0a,d2
int main ()
{
// Parse the string of data into a std::vector<std::tuple<std::string,jsoncons::byte_string,std::string>> value
auto val = cbor::decode_cbor<std::vector<std::tuple<std::string,jsoncons::byte_string,std::string>>>(data);
std::cout << " (1) n " ;
for ( const auto & row : val)
{
std::cout << std::get< 0 >(row) << " , " << std::get< 1 >(row) << " , " << std::get< 2 >(row) << " n " ;
}
std::cout << " n " ;
// Serialize back to CBOR
std::vector< uint8_t > buffer;
cbor::encode_cbor (val, buffer);
std::cout << " (2) n " << byte_string_view (buffer) << " nn " ;
}
Ausgabe:
(1)
foo, 50,75,73,73, 0x3p-1
bar, 50,75,73,73, 1.23456789012345678901234567890
(2)
82,9f,63,66,6f,6f,44,50,75,73,73,66,30,78,33,70,2d,31,ff,9f,63,62,61,72,44,50,75,73,73,78,1f,31,2e,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,31,32,33,34,35,36,37,38,39,30,ff
Beachten Sie, dass wir bei der Dekodierung des Bigfloat- und Dezimalbruchs in einen std::string
die semantischen Informationen verlieren, die die variantenähnliche Datenstruktur mit einem Tag bewahrt, sodass bei der Serialisierung zurück zu CBOR eine Textzeichenfolge entsteht.
Eine typische Pull-Parsing-Anwendung verarbeitet das Ereignis current()
wiederholt und ruft next()
auf, um zum nächsten Ereignis zu gelangen, bis done()
true
zurückgibt.
int main ()
{
cbor::cbor_bytes_cursor cursor (data);
for (; !cursor. done (); cursor. next ())
{
const auto & event = cursor. current ();
switch (event. event_type ())
{
case staj_event_type::begin_array:
std::cout << event. event_type () << " " << " ( " << event. tag () << " ) n " ;
break ;
case staj_event_type::end_array:
std::cout << event. event_type () << " " << " ( " << event. tag () << " ) n " ;
break ;
case staj_event_type::begin_object:
std::cout << event. event_type () << " " << " ( " << event. tag () << " ) n " ;
break ;
case staj_event_type::end_object:
std::cout << event. event_type () << " " << " ( " << event. tag () << " ) n " ;
break ;
case staj_event_type::key:
// Or std::string_view, if supported
std::cout << event. event_type () << " : " << event. get <jsoncons::string_view>() << " " << " ( " << event. tag () << " ) n " ;
break ;
case staj_event_type::string_value:
// Or std::string_view, if supported
std::cout << event. event_type () << " : " << event. get <jsoncons::string_view>() << " " << " ( " << event. tag () << " ) n " ;
break ;
case staj_event_type::byte_string_value:
std::cout << event. event_type () << " : " << event. get <jsoncons::span< const uint8_t >>() << " " << " ( " << event. tag () << " ) n " ;
break ;
case staj_event_type::null_value:
std::cout << event. event_type () << " " << " ( " << event. tag () << " ) n " ;
break ;
case staj_event_type::bool_value:
std::cout << event. event_type () << " : " << std::boolalpha << event. get < bool >() << " " << " ( " << event. tag () << " ) n " ;
break ;
case staj_event_type::int64_value:
std::cout << event. event_type () << " : " << event. get < int64_t >() << " " << " ( " << event. tag () << " ) n " ;
break ;
case staj_event_type::uint64_value:
std::cout << event. event_type () << " : " << event. get < uint64_t >() << " " << " ( " << event. tag () << " ) n " ;
break ;
case staj_event_type::half_value:
case staj_event_type::double_value:
std::cout << event. event_type () << " : " << event. get < double >() << " " << " ( " << event. tag () << " ) n " ;
break ;
default :
std::cout << " Unhandled event type " << event. event_type () << " " << " ( " << event. tag () << " ) n " ;
break ;
}
}
}
Ausgabe:
begin_array (n/a)
begin_array (n/a)
string_value: foo (n/a)
byte_string_value: 50,75,73,73 (n/a)
string_value: 0x3p-1 (bigfloat)
end_array (n/a)
begin_array (n/a)
string_value: bar (n/a)
byte_string_value: 50,75,73,73 (base64)
string_value: 1.23456789012345678901234567890 (bigdec)
end_array (n/a)
end_array (n/a)
Sie können mithilfe der Pipe-Syntax einen Filter auf einen Cursor anwenden.
int main ()
{
auto filter = [&]( const staj_event& ev, const ser_context&) -> bool
{
return (ev. tag () == semantic_tag::bigdec) || (ev. tag () == semantic_tag::bigfloat);
};
cbor::cbor_bytes_cursor cursor (data);
auto filtered_c = cursor | filter;
for (; !filtered_c. done (); filtered_c. next ())
{
const auto & event = filtered_c. current ();
switch (event. event_type ())
{
case staj_event_type::string_value:
// Or std::string_view, if supported
std::cout << event. event_type () << " : " << event. get <jsoncons::string_view>() << " " << " ( " << event. tag () << " ) n " ;
break ;
default :
std::cout << " Unhandled event type " << event. event_type () << " " << " ( " << event. tag () << " ) n " ;
break ;
}
}
}
Ausgabe:
string_value: 0x3p-1 (bigfloat)
string_value: 1.23456789012345678901234567890 (bigdec)
jsoncons erfordert einen Compiler mit minimaler C++11-Unterstützung. Es wird in kontinuierlicher Integration auf Github Actions und Circleci getestet. Die UndefinedBehaviorSanitizer (UBSan)-Diagnose ist für ausgewählte gcc- und clang-Builds aktiviert. Seit v0.151.0 ist es in Google OSS-fuzz integriert und deckt alle Parser und Encoder ab.
Compiler | Version | Standard | Architektur | Betriebssystem | CI-Dienst |
---|---|---|---|---|---|
Visual Studio | vs2019 | Standard | x86, x64 | Windows 11 | GitHub-Aktionen |
vs2022 | Standard | x86, x64 | Windows 11 | GitHub-Aktionen | |
Visual Studio – Klirren | vs2019 | Standard | x86, x64 | Windows 11 | GitHub-Aktionen |
vs2022 | Standard | x86, x64 | Windows 11 | GitHub-Aktionen | |
g++ | 6, 7, 8, 9, 10, 11, 12 | Standard | x64 | Ubuntu | Kreisci |
g++ | 12 | c++20 | x64 | Ubuntu | GitHub-Aktionen |
klirren | 3,9, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 | Standard | x64 | Ubuntu | Kreisci |
klirren | 14 | c++20 | x64 | Ubuntu | GitHub-Aktionen |
clang xcode | 11, 12, 13 | Standard | x64 | OSX 11 | GitHub-Aktionen |
clang xcode | 13, 14 | Standard | x64 | OSX 12 | GitHub-Aktionen |
CMake ist ein plattformübergreifendes Build-Tool, das Makefiles und Lösungen für die Compiler-Umgebung Ihrer Wahl generiert. Unter Windows können Sie ein Windows Installer-Paket herunterladen. Unter Linux ist es normalerweise als Paket verfügbar, z. B. unter Ubuntu.
sudo apt-get install cmake
Sobald cmake installiert ist, können Sie die Komponententests im jsoncons-Verzeichnis erstellen und ausführen.
Unter Windows:
> mkdir build
> cd build
> cmake .. -DJSONCONS_BUILD_TESTS=On
> cmake --build .
> ctest -C Debug --output-on-failure
Unter UNIX:
$ mkdir build
$ cd build
$ cmake .. -DJSONCONS_BUILD_TESTS=On
$ cmake --build .
$ ctest --output-on-failure
jsoncons verwendet den statischen Analysator PVS-Studio, der kostenlos für Open-Source-Projekte bereitgestellt wird.
Ein großes Dankeschön an die comp.lang.c++-Community für die Hilfe bei den Implementierungsdetails.
Die plattformabhängige Binärkonfiguration von jsoncons basiert auf dem hervorragenden MIT-lizenzierten Tinycbor.
Vielen Dank an Milo Yip, Autor von RapidJSON, für die allgemeine Verbesserung der Qualität von JSON-Bibliotheken durch die Veröffentlichung der Benchmarks und die Kontaktaufnahme mit diesem Projekt (unter anderem), um die Ergebnisse zu teilen.
Die jsoncons-Implementierung des Grisu3-Algorithmus zum Drucken von Gleitkommazahlen folgt mit geringfügigen Änderungen der MIT-lizenzierten grisu3_59_56-Implementierung von Florian Loitsch.
Das Makro JSONCONS_ALL_MEMBER_TRAITS
folgt dem Ansatz von Martin Yorks ThorsSerializer
Die JSONCONS-Implementierungen von BSON decimal128 zu und von String und ObjectId zu und von String basieren auf dem für Apache 2 lizenzierten LIBBSON.
Besonderer Dank geht an unsere Mitwirkenden