web-dev-qa-db-fra.com

Récupération d'un objet imbriqué dans une chaîne JSON à l'aide de rapidjson

Je dois récupérer un objet imbriqué dans une chaîne JSON et j'essaie de le faire avec rapidjson. Tout ce que j'ai trouvé, c'est comment récupérer des tableaux et des types de base, mais pas des sous-objets. J'ai créé l'exemple de jouet suivant qui donne une erreur:

rapidjson::Document document;
std::string test =  " { \"a\": { \"z\" : 21 } } ";
std::cout << test << std::endl;
if ( document.Parse<0>( test.c_str() ).HasParseError() ) {
    std::cout << "Parsing error" << std::endl;
} else {
    if ( document[ "a" ].IsObject() ) {
        std::cout << "OK" << std::endl;
        std::cout << document[ "a" ].GetString() << std::endl;
    }
}

Voici le résultat à l'exécution:

{ "a": { "z" : 21 } } 
OK
JSONTest: ../rapidjson/document.h:441: const typename Encoding::Ch* rapidjson::GenericValue<Encoding, Allocator>::GetString() const [with Encoding = rapidjson::UTF8<char>, Allocator = rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>]: Assertion `IsString()' failed. Aborted

Comment puis-je récupérer l'objet interne pour continuer mon analyse? Merci.

Edit : Ce dont j'ai besoin, c'est d'obtenir la représentation sous forme de chaîne de l'objet interne afin de pouvoir appeler une autre fonction qui va l'analyser.

Edit 2 : code permettant de récupérer l'objet interne sous forme de chaîne:

rapidjson::Document document;
std::string test =  "{\"a\":{\"z\":21}} ";
if ( document.Parse<0>( test.c_str() ).HasParseError() ) {
    std::cout << "Error parsing" << std::endl;
} else {
    if ( document[ "a" ].IsObject() ) {
        rapidjson::StringBuffer sb;
        rapidjson::Writer<rapidjson::StringBuffer> writer( sb );
        document[ "a" ].Accept( writer );
        std::cout << sb.GetString() << std::endl;
    }
}
13
pparescasellas

Vous devez parcourir manuellement les membres de l'objet, car GetString () ne fonctionne que sur les membres de chaîne, tandis que document ["a"] est un objet. Vous devez parcourir les membres de cet objet à l'aide de la variable MemberIterator. Je n'ai pas pratiqué le C * depuis plus de 15 ans, je ne peux donc donner qu'une idée générale de la façon dont cela devrait fonctionner:

for (MemberIterator m = document["a"].MemberBegin(); m != document["a"].MemberEnd(); ++m) {
    std::cout << m.name << " " << (m.IsNumber()?m.GetNumber():m.GetString()) << endl;
}

Aussi, vous voudrez peut-être regarder la méthode Accept (), elle semble renvoyer une chaîne JSON d'un objet que vous lui donnez.

7
Vesper

Si element est un objet, vous pouvez simplement accéder aux sous-propriétés avec []:

for (SizeType i = 0; i < layers.Size(); i++){   
  cout << layers[i]["name"].GetString() << endl;
}
3
lasote

Il existe une autre excellente approche réalisée dans rapidjson - JSON Pointers . Ils ont un statut expérimental et, conformément à la documentation, doivent être inclus dans v.1.1. Quoi qu'il en soit, cette approche ressemble à XPATH pour XML. Pour obtenir une valeur imbriquée, nous pouvons utiliser la syntaxe suivante: 

Value* tmpValue = GetValueByPointer(doc, "/result/job/blob");

J'ai essayé cette fonctionnalité et à mon avis c'est mieux que les itérateurs.

1
Kostia Shiian

Vous pouvez utiliser un pointeur pour obtenir le sous-objet:

Value& a = *GetValueByPointer(document, "/a");
int z = a["z"].GetInt();
0
Michael