2010-01-22 3 views
58

Sto provando a creare un array JSON utilizzando gli alberi di proprietà boost.Creazione di array JSON in Boost utilizzando gli alberi delle proprietà

documentation dice: "Gli array JSON sono mappati ai nodi, ogni elemento è un nodo figlio con un nome vuoto."

Quindi mi piacerebbe creare un albero delle proprietà con nomi vuoti, quindi chiamare write_json(...) per ottenere l'array. Tuttavia, la documentazione non mi dice come creare nodi figlio senza nome. Ho provato ptree.add_child("", value), ma questo produce:

Assertion `!p.empty() && "Empty path not allowed for put_child."' failed 

La documentazione non sembra affrontare questo punto, almeno non nel senso che posso capire. Qualcuno può aiutare?

risposta

19

Quello che devi fare è questo pezzo di divertimento. Questo viene dalla memoria, ma qualcosa come questo funziona per me.

boost::property_tree::ptree root; 
boost::property_tree::ptree child1; 
boost::property_tree::ptree child2; 

// .. fill in children here with what you want 
// ... 

ptree.push_back(std::make_pair("", child1)); 
ptree.push_back(std::make_pair("", child2)); 

Ma attenzione ci sono diversi bug nell'analisi e scrittura di json. Molti dei quali ho presentato segnalazioni di bug per - con nessuna risposta :(

EDIT: per rispondere alla preoccupazione a questo proposito la serializzazione in modo errato come { "": "", "": ""}

questo accade solo . quando la matrice è l'elemento principale lo scrittore spinta ptree tratta tutti elementi radice come oggetti -. mai array o valori Ciò è causato dalla seguente riga nella boost/propert_tree/dettaglio/json_parser_writer.hpp

else if (indent > 0 && pt.count(Str()) == pt.size()) 

sbarazzarsi del "rientro> 0 & &" consentirà di scrivere correttamente gli array.

Se non ti piace quanto spazio viene prodotto è possibile utilizzare la patch ho fornito here

+0

Questo non è giusto. Dopo aver scaricato su JSON, anziché ottenere un array, ottengo questo: {"": "", "": ""}. –

+0

Aggiornato il post per riflettere perché questo sta accadendo e come risolverlo. –

+0

Triste per segnalare che sembra ancora impossibile creare matrici come elementi radice in 1.53.0. – conciliator

10

Quando si inizia a usare Albero proprietà per rappresentare una struttura JSON ho incontrato problemi simili che non ha risolto. Si noti inoltre che dalla documentazione l'albero delle proprietà non supporta completamente le informazioni sul tipo:

I valori JSON sono mappati ai nodi che contengono il valore. Tuttavia, tutte le informazioni sul tipo sono perse; i numeri, così come i letterali "null", "true" e "false" sono semplicemente mappati alla loro forma di stringa.

Dopo aver appreso ciò, sono passato all'implementazione JSON più completa JSON Spirit. Questa libreria utilizza Boost Spirit per l'implementazione della grammatica JSON e supporta pienamente JSON, inclusi gli array.

Suggerisco di utilizzare un'implementazione JSON C++ alternativa.

+0

Un sacco di nuove librerie da quando ho scritto questa risposta. Ecco una bella che ho trovato di recente: https://github.com/nlohmann/json – Yukiko

6

Nel mio caso ho voluto aggiungere un array a una posizione più o meno arbitrario, così, come la risposta di Michael, creare un albero bambino e popolarlo con elementi di un array:

using boost::property_tree::ptree; 

ptree targetTree; 
ptree arrayChild; 
ptree arrayElement; 

//add array elements as desired, loop, whatever, for example 
for(int i = 0; i < 3; i++) 
{ 
    arrayElement.put_value(i); 
    arrayChild.push_back(std::make_pair("",arrayElement)) 
} 

Quando il bambino è stato popolato, utilizzare la funzione put_child() o add_child() per aggiungere l'intero albero figlio all'albero di destinazione, in questo modo ...

targetTree.put_child(ptree::path_type("target.path.to.array"),arrayChild) 

la funzione put_child prende un percorso e un albero per un argomento e volontà arrayChild "graft" in targetTree

84

semplice array:

#include <boost/property_tree/ptree.hpp> 
using boost::property_tree::ptree; 

ptree pt; 
ptree children; 
ptree child1, child2, child3; 

child1.put("", 1); 
child2.put("", 2); 
child3.put("", 3); 

children.push_back(std::make_pair("", child1)); 
children.push_back(std::make_pair("", child2)); 
children.push_back(std::make_pair("", child3)); 

pt.add_child("MyArray", children); 

write_json("test1.json", pt); 

risultati in:

{ 
    "MyArray": 
    [ 
     "1", 
     "2", 
     "3" 
    ] 
} 

Matrice su oggetti:

ptree pt; 
ptree children; 
ptree child1, child2, child3; 


child1.put("childkeyA", 1); 
child1.put("childkeyB", 2); 

child2.put("childkeyA", 3); 
child2.put("childkeyB", 4); 

child3.put("childkeyA", 5); 
child3.put("childkeyB", 6); 

children.push_back(std::make_pair("", child1)); 
children.push_back(std::make_pair("", child2)); 
children.push_back(std::make_pair("", child3)); 

pt.put("testkey", "testvalue"); 
pt.add_child("MyArray", children); 

write_json("test2.json", pt); 

risultati in:

{ 
    "testkey": "testvalue", 
    "MyArray": 
    [ 
     { 
      "childkeyA": "1", 
      "childkeyB": "2" 
     }, 
     { 
      "childkeyA": "3", 
      "childkeyB": "4" 
     }, 
     { 
      "childkeyA": "5", 
      "childkeyB": "6" 
     } 
    ] 
} 

speranza che questo aiuta

+3

Si prega di notare che i numeri sono codificati come stringhe e non numeri. – Luke

+0

Ciao @Luke, sto riscontrando questo problema con le stringhe. Come posso codificarli come numeri? – Alejandro

+3

Non sono riuscito a trovare una buona soluzione quando si utilizza la libreria boost. Sono passato a rapidjson invece. – Luke