jsoncons est une bibliothèque C++ uniquement en-tête pour construire des formats de données JSON et de type JSON tels que CBOR. Pour chaque format de données pris en charge, il vous permet de travailler avec les données de plusieurs manières :
En tant que structure de données de type variante, sensible à l'allocateur, basic_json
En tant que structure de données C++ fortement typée qui implémente json_type_traits
Avec un accès au niveau du curseur à un flux d'événements d'analyse, quelque peu analogue à l'analyse pull StAX et à la sérialisation push dans le monde XML.
Comparé à d'autres bibliothèques JSON, jsoncons a été conçu pour gérer de très gros textes JSON. En son cœur se trouvent les analyseurs et sérialiseurs de style SAX. Il prend en charge la lecture d'un texte JSON entier en mémoire dans une structure de type variante. Mais il prend également en charge un accès efficace aux données sous-jacentes à l’aide de l’analyse pull et de la sérialisation push de style StAX. Et il prend en charge l'analyse incrémentielle dans la forme préférée d'un utilisateur, en utilisant les informations sur les types d'utilisateurs fournies par les spécialisations de json_type_traits.
Le modèle de données jsoncons prend en charge les types JSON familiers : valeurs nulles, booléennes, nombres, chaînes, tableaux, objets, ainsi que les chaînes d'octets. De plus, jsoncons prend en charge le balisage sémantique des dates-heures, des époques, des grands entiers, des grandes décimales, des grands flottants et des encodages binaires. Cela lui permet de conserver ces sémantiques de type lors de l'analyse des formats de données de type JSON tels que CBOR qui les contiennent.
jsoncons est distribué sous la licence logicielle Boost.
jsoncons est gratuit mais accueille favorablement un soutien pour soutenir son développement. Si vous trouvez cette bibliothèque utile, pensez à faire un don unique ou à devenir sponsor ❤️.
Au fur et à mesure de l'évolution de la bibliothèque jsoncons
, les noms ont parfois changé. Pour faciliter la transition, jsoncons déprécie les anciens noms mais continue d'en prendre en charge bon nombre. Les noms obsolètes peuvent être supprimés en définissant la macro JSONCONS_NO_DEPRECATED
, et cela est recommandé pour le nouveau code.
"Apache Kvrocks utilise systématiquement jsoncons pour offrir aux utilisateurs la prise en charge des structures de données JSON. Nous trouvons l'expérience de développement avec jsoncons exceptionnelle !"
"J'utilise votre bibliothèque dans ma langue maternelle - R - et j'ai créé un package R facilitant (a) les requêtes JMESpath et JSONpath sur des chaînes JSON ou des objets R et (b) permettant aux autres développeurs R de créer un lien vers votre bibliothèque. ".
"J'utilise votre bibliothèque comme interface externe pour transmettre des données, ainsi que pour utiliser les conversions de csv en json, qui sont très utiles pour convertir des données à utiliser en javascript"
"Vérifié que, pour mes besoins en JSON et CBOR, cela fonctionne parfaitement"
"la fonctionnalité JSONPath de cette bibliothèque, c'est génial"
"Nous utilisons assez largement l'implémentation de JMESPath"
"Nous adorons votre validateur de schéma JSON. Nous l'utilisons dans ER/Studio, notre outil de modélisation de données pour analyser les fichiers de schéma JSON afin de pouvoir créer des modèles de relations d'entité à partir d'eux."
"la bibliothèque de sérialisation de choix avec ses superbes mappages et sa facilité d'utilisation"
"vraiment bien" "projet génial" "très solide et très fiable" "mon équipe l'adore" "Votre repo est génial !!!!"
Démarrez avec les ensembles d'images et les cadres d'images HealthImaging à l'aide d'un kit SDK AWS
RubyGems.org rjsoncons Coppelia Robotics Licences CSPro
Vous pouvez utiliser le gestionnaire de bibliothèque de la plateforme vcpkg pour installer le package jsoncons.
Ou téléchargez la dernière version et décompressez le fichier zip. Copiez le répertoire include/jsoncons
dans votre répertoire include
. Si vous souhaitez utiliser des extensions, copiez également include/jsoncons_ext
.
Ou téléchargez le dernier code sur main.
La bibliothèque nécessite un compilateur C++ avec prise en charge C++11. De plus, la bibliothèque définit jsoncons::endian
, jsoncons::basic_string_view
, jsoncons::optional
et jsoncons::span
, qui seront typés selon leurs équivalents de bibliothèque standard s'ils sont détectés. Sinon, ils seront typés dans des implémentations internes, compatibles C++11.
La bibliothèque utilise des exceptions et, dans certains cas, des std::error_code pour signaler les erreurs. Outre jsoncons::assertion_error
, toutes les classes d'exceptions jsoncons implémentent l'interface jsoncons::json_error. Si les exceptions sont désactivées ou si la macro de compilation JSONCONS_NO_EXCEPTIONS
est définie, les lancers deviennent des appels à std::terminate
.
json_benchmarks fournit quelques mesures sur la façon dont jsoncons
se compare aux autres bibliothèques json
.
Suites de tests JSONTestSuite et JSON_checker
Benchmarks de performances avec du texte et des entiers
Benchmarks de performances avec texte et doubles
La comparaison JSONPath montre comment jsoncons JsonPath se compare à d'autres implémentations
Travailler avec des données JSON
Travailler avec des données CBOR
Pour les exemples ci-dessous, vous devez inclure des fichiers d'en-tête et initialiser une chaîne de données JSON :
# 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
}
]
}
)" ;
jsoncons vous permet de travailler avec les données de plusieurs manières :
En tant que structure de données de type variante, basic_json
En tant que structure de données C++ fortement typée qui implémente json_type_traits
Avec un accès au niveau du curseur à un flux d'événements d'analyse
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 " ;
}
Sortir:
(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 prend en charge la transformation des textes JSON en structures de données C++. Les fonctions decode_json et encode_json convertissent des chaînes ou des flux de données JSON en structures de données C++ et inversement. Décodez et encodez le travail pour toutes les classes C++ pour lesquelles json_type_traits est défini. jsoncons prend déjà en charge de nombreux types dans la bibliothèque standard, et vos propres types seront également pris en charge si vous spécialisez json_type_traits
dans l'espace de noms jsoncons
.
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 " ;
}
Sortir:
(1)
Marilyn C, 0.9, 1514862245
(2)
{
"application": "hiking",
"reputons": [
{
"assertion": "advanced",
"generated": 1514862245,
"rated": "Marilyn C",
"rater": "HikingAsylum",
"rating": 0.9
}
]
}
Cet exemple utilise les macros pratiques JSONCONS_ENUM_TRAITS
, JSONCONS_N_CTOR_GETTER_TRAITS
et JSONCONS_ALL_CTOR_GETTER_TRAITS
pour spécialiser les json_type_traits pour le type d'énumération ns::hiking_experience
, la classe ns::hiking_reputon
(avec certains membres non obligatoires) et la classe ns::hiking_reputation
(avec tous les membres obligatoires.) La macro JSONCONS_ENUM_TRAITS
génère le code à partir des identifiants enum, et les macros JSONCONS_N_CTOR_GETTER_TRAITS
et JSONCONS_ALL_CTOR_GETTER_TRAITS
génèrent le code à partir des fonctions get et d'un constructeur. Ces déclarations de macro doivent être placées en dehors de tout bloc d'espace de noms.
Voir des exemples pour d'autres façons de spécialiser json_type_traits
.
Une application d'analyse pull typique traitera à plusieurs reprises l'événement current()
et appellera next()
pour passer à l'événement suivant, jusqu'à ce que done()
renvoie true
.
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 ;
}
}
}
Sortir:
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
Vous pouvez appliquer un filtre à un curseur en utilisant la syntaxe pipe (par exemple, 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 ;
}
}
}
Sortir:
Marilyn C
Pour les exemples ci-dessous, vous devez inclure des fichiers d'en-tête et initialiser un tampon de données CBOR :
# 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"
};
jsoncons vous permet de travailler avec les données CBOR de la même manière que les données JSON :
En tant que structure de données de type variante, basic_json
En tant que structure de données C++ fortement typée qui implémente json_type_traits
Avec un accès au niveau du curseur à un flux d'événements d'analyse
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 " ;
}
Sortir:
(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 " ;
}
Sortir:
(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
Notez que lors du décodage du bigfloat et de la fraction décimale en un std::string
, nous perdons les informations sémantiques que la variante comme la structure de données a préservées avec une balise, donc la sérialisation vers CBOR produit une chaîne de texte.
Une application d'analyse pull typique traitera à plusieurs reprises l'événement current()
et appellera next()
pour passer à l'événement suivant, jusqu'à ce que done()
renvoie true
.
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 ;
}
}
}
Sortir:
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)
Vous pouvez appliquer un filtre à un curseur en utilisant la syntaxe du tube,
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 ;
}
}
}
Sortir:
string_value: 0x3p-1 (bigfloat)
string_value: 1.23456789012345678901234567890 (bigdec)
jsoncons nécessite un compilateur avec une prise en charge minimale de C++11. Il est testé en intégration continue sur Github Actions et circleci. Les diagnostics UndefinedBehaviorSanitizer (UBSan) sont activés pour les versions gcc et clang sélectionnées. Depuis la version 0.151.0, il est intégré à Google OSS-fuzz, avec une couverture pour tous les analyseurs et encodeurs.
Compilateur | Version | Standard | Architecture | Système opérateur | Service CI |
---|---|---|---|---|---|
Studio visuel | vs2019 | défaut | x86, x64 | Windows 11 | Actions GitHub |
vs2022 | défaut | x86, x64 | Windows 11 | Actions GitHub | |
Visual Studio-clang | vs2019 | défaut | x86, x64 | Windows 11 | Actions GitHub |
vs2022 | défaut | x86, x64 | Windows 11 | Actions GitHub | |
g++ | 6, 7, 8, 9, 10, 11, 12 | défaut | x64 | Ubuntu | cercleci |
g++ | 12 | c++20 | x64 | Ubuntu | Actions GitHub |
bruit | 3,9, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 | défaut | x64 | Ubuntu | cercleci |
bruit | 14 | c++20 | x64 | Ubuntu | Actions GitHub |
clangxcode | 11, 12, 13 | défaut | x64 | OSX11 | Actions GitHub |
clangxcode | 13, 14 | défaut | x64 | OSX12 | Actions GitHub |
CMake est un outil de construction multiplateforme qui génère des makefiles et des solutions pour l'environnement de compilateur de votre choix. Sous Windows, vous pouvez télécharger un package Windows Installer. Sous Linux, il est généralement disponible sous forme de package, par exemple sur Ubuntu,
sudo apt-get install cmake
Une fois cmake installé, vous pouvez créer et exécuter les tests unitaires à partir du répertoire jsoncons,
Sous Windows :
> mkdir build
> cd build
> cmake .. -DJSONCONS_BUILD_TESTS=On
> cmake --build .
> ctest -C Debug --output-on-failure
Sous UNIX :
$ mkdir build
$ cd build
$ cmake .. -DJSONCONS_BUILD_TESTS=On
$ cmake --build .
$ ctest --output-on-failure
jsoncons utilise l'analyseur statique PVS-Studio, fourni gratuitement pour les projets open source.
Un grand merci à la communauté comp.lang.c++ pour son aide sur les détails d'implémentation.
La configuration binaire dépendante de la plate-forme jsoncons s'appuie sur l'excellent tinycbor sous licence MIT.
Merci à Milo Yip, auteur de RapidJSON, d'avoir amélioré la qualité des bibliothèques JSON à tous les niveaux, en publiant les benchmarks et en contactant ce projet (entre autres) pour partager les résultats.
L'implémentation jsoncons de l'algorithme Grisu3 pour l'impression de nombres à virgule flottante suit l'implémentation grisu3_59_56 sous licence MIT de Florian Loitsch, avec des modifications mineures.
La macro JSONCONS_ALL_MEMBER_TRAITS
suit l'approche adoptée par ThorsSerializer de Martin York
Les implémentations jsoncons de BSON decimal128 vers et depuis une chaîne, et ObjectId vers et depuis une chaîne, sont basées sur la licence libbson Apache 2.
Un merci spécial à nos contributeurs