2010-01-22 15 views
58

Estoy intentando crear una matriz JSON utilizando los árboles de propiedades boost.Creación de matrices JSON en Boost usando árboles de propiedades

dice: "Las matrices JSON se asignan a nodos.

Así que me gustaría crear un árbol de propiedades con nombres vacíos, luego llamar al write_json(...) para obtener la matriz. Sin embargo, la documentación no me dice cómo crear nodos secundarios sin nombre. Probé ptree.add_child("", value), pero esto produce: no parece

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

La documentación para hacer frente a este punto, al menos no de una manera que puedo imaginar. ¿Alguien puede ayudar?

Respuesta

19

Lo que necesitas hacer es esta pieza de diversión. Esto es de memoria, pero algo como esto me funciona.

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)); 

Pero ten en cuenta que hay varios errores en el análisis y la escritura json. Varios de los cuales me he presentado informes de errores para - sin respuesta :(

EDIT: para hacer frente a la preocupación por que la serialización de forma incorrecta como { "": "", "": ""}

Esto sólo sucede . cuando la matriz es el elemento raíz el escritor impulso ptree trata a todos los elementos raíz como objetos -. nunca matrices o valores Esto es causado por la siguiente línea en realce/propert_tree/detalle/json_parser_writer.hpp

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

deshacerse del "sangrado> 0 & &" le permitirá escribir matrices correctamente.

Si no te gusta la cantidad de espacio se produce puede utilizar el parche que he proporcionado here

+0

Esto no es correcto. Después de descargar en JSON, en lugar de obtener una matriz, obtengo esto: {"": "", "": ""}. –

+0

Actualicé la publicación para reflejar por qué sucede esto y cómo solucionarlo. –

+0

Es triste informar que parece que todavía es imposible crear matrices como elementos raíz en 1.53.0. – conciliator

10

Al comenzar a utilizar la propiedad de árbol para representar una estructura JSON me encontré con problemas similares que yo no resolvió. También tenga en cuenta que, a partir de la documentación, el árbol de propiedades no es totalmente compatible con la información del tipo:

Los valores JSON se asignan a los nodos que contienen el valor. Sin embargo, se pierde toda la información de tipo; los números, así como los literales "nulo", "verdadero" y "falso" simplemente se asignan a su forma de cadena.

Después de aprender esto, cambié a la implementación más completa de JSON JSON Spirit. Esta biblioteca utiliza Boost Spirit para la implementación de la gramática JSON y es totalmente compatible con JSON, incluidas las matrices.

Le sugiero que utilice una implementación C++ JSON alternativa.

+0

Muchas bibliotecas nuevas desde que escribí esta respuesta. Aquí hay uno bueno que me encontré recientemente: https://github.com/nlohmann/json – Yukiko

6

En mi caso, yo quería añadir una matriz a un lugar más o menos arbitraria, por lo que, al igual que la respuesta de Michael, crear un árbol de niños y rellenarlo con elementos de la matriz:

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)) 
} 

Cuando el niño ha sido poblado, use la función put_child() o add_child() para agregar el árbol secundario completo al árbol de destino, como este ...

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

la función put_child toma un camino y un árbol por un argumento y lo hará arrayChild "injerto" en targetTree

84

de matriz simple:

#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); 

resultados en:

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

Matriz sobre objetos:

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); 

resultados en:

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

esperanza esto ayuda

+3

Tenga en cuenta que los números están codificados como cadenas y no como números. – Luke

+0

Hola @Luke, estoy teniendo este problema con las cuerdas. ¿Cómo puedo codificarlos como números? – Alejandro

+3

No pude encontrar una buena solución cuando uso la biblioteca de impulso. Cambié a rapidjson en su lugar. – Luke