Warum funktioniert Boost-Eigenschaftsbaum write_json speichern alles als String? Ist es möglich, das zu ändern?

StackOverflow https://stackoverflow.com/questions/2855741

  •  27-09-2019
  •  | 
  •  

Frage

Ich versuche, mit boost Eigenschaftsbaum write_json zu serialisiert, es spart alles wie Saiten, es ist nicht, dass die Daten falsch sind, aber ich brauche sie ausdrücklich jedes Mal zu werfen, und ich möchte, dass sie sonst irgendwo verwenden. (Wie in Python oder andere C ++ json (nicht Boost) Bibliothek)

Hier ist ein Beispielcode und was wir bekommen je nach Region:

boost::property_tree::ptree root, arr, elem1, elem2;
elem1.put<int>("key0", 0);
elem1.put<bool>("key1", true);
elem2.put<float>("key2", 2.2f);
elem2.put<double>("key3", 3.3);
arr.push_back( std::make_pair("", elem1) );
arr.push_back( std::make_pair("", elem2) );
root.put_child("path1.path2", arr);

std::stringstream ss;
write_json(ss, root);
std::string my_string_to_send_somewhare_else = ss.str();

und my_string_to_send_somewhere_else ist etw. wie folgt aus:

{
    "path1" :
    {
       "path2" :
       [
            {
                 "key0" : "0",
                 "key1" : "true"
            },
            {
                 "key2" : "2.2",
                 "key3" : "3.3"
            }
       ]
    }
}

Gibt es trotzdem, sie als die Werte zu speichern, wie: "key1" : true oder "key2" : 2.2?

War es hilfreich?

Lösung

Die einfachste und sauberste Lösung, die ich tun konnte, war die JSON mit Platzhalter zu erzeugen und in dem End-String mit dem aktuellen Wert ersetzt die zusätzlichen Anführungszeichen Notwasserung.

static string buildGetOrdersCommand() {
    ptree root;
    ptree element;
    element.put<string>("pendingOnly", ":pendingOnly");
    element.put<string>("someIntValue", ":someIntValue");

    root.put("command", "getOrders");
    root.put_child("arguments", element);

    std::ostringstream buf;
    write_json(buf, root, false);
    buf << std::endl;

    string json = buf.str();
    replace(json, ":pendingOnly", "true");
    replace(json, ":someIntValue", std::to_string(15));

    return json;
}

static void replace(string& json, const string& placeholder, const string& value) {
    boost::replace_all<string>(json, "\"" + placeholder + "\"", value);
}

Und das Ergebnis ist

  

{ "Befehl": "GetOrders", "Argumente": { "pendingOnly": true, "someIntValue": 15}}

Andere Tipps

Ok, ich habe es so gelöst, (natürlich wird es nicht Suite für alle, da es ein bisschen wie ein Hack ist, dass die weitere Arbeit benötigen).


Ich habe meine eigene write_json Funktion (einfach kopiert die Dateien, json_parser.hpp und json_parser_write.hpp mein Projekt) schrieb und die folgenden Zeilen in json_parser_write.hpp geändert:

  1. Kommentarzeile 37 - Flucht aus dem Zitat " '
  2. geändert Linie 76 -, so dass sie nicht hinzufügen, zitiert mehr: stream << Ch('"') << data << Ch('"'); ==> stream << data;

Dann werden Werte richtig außer für Strings gespeichert werden, so dass ich benutzerdefinierten Übersetzer für sich schrieb:

template <typename T>
struct my_id_translator
{
    typedef T internal_type;
    typedef T external_type;

    boost::optional<T> get_value(const T &v) { return  v.substr(1, v.size() - 2) ; }
    boost::optional<T> put_value(const T &v) { return '"' + v +'"'; }
};

und einfach gespeichert Zeichenfolge mit:

elem2.put<std::string>("key2", "asdf", my_id_translator<std::string>());

komplettes Programm:

#include <iostream>
#include <string>
#include <sstream>

#include <boost/property_tree/ptree.hpp>

#include "property_tree/json_parser.hpp" // copied the headers

template <typename T>

struct my_id_translator
{
    typedef T internal_type;
    typedef T external_type;

    boost::optional<T> get_value(const T &v) { return  v.substr(1, v.size() - 2) ; }
    boost::optional<T> put_value(const T &v) { return '"' + v +'"'; }
};

int main(int, char *[])
{
    using namespace std;
    using boost::property_tree::ptree;
    using boost::property_tree::basic_ptree;
    try
    {
        ptree root, arr,elem2;
        basic_ptree<std::string, std::string> elem1;
        elem1.put<int>("int", 10 );
        elem1.put<bool>("bool", true);
        elem2.put<double>("double", 2.2);
        elem2.put<std::string>("string", "some string", my_id_translator<std::string>());

        arr.push_back( std::make_pair("", elem1) );
        arr.push_back( std::make_pair("", elem2) );
        root.put_child("path1.path2", arr);

        std::stringstream ss;
        write_json(ss, root);
        std::string my_string_to_send_somewhere_else = ss.str();

        cout << my_string_to_send_somewhere_else << endl;

    }
    catch (std::exception & e)
    {
        cout << e.what();
    }
    return 0;
}

Ergebnis:)

{
    "path1":
    {
        "path2":
        [
            {
                "int": 10,
                "bool": true
            },
            {
                "double": 2.2,
                "string": "some string"
            }
        ]
    }
}

Erhöhung bestätigt seine Umsetzung zu JSON-Standard keine 100% Konformität hat. Überprüfen Sie den folgenden Link ihre Erklärung zu sehen: Eine ptree Variante, dass Konserven JSON-Typ ein Plan für die Zukunft ist, aber weit weg. !

Da wir typedef basic_ptree ptree; in den Boost-Bibliotheken, auftrieb wird immer jeden Wert als String serialisiert und alle Werte auf eine entsprechende Zeichenfolge analysieren.

Von der ausgegebenen JSON ist es klar, dass die alles serialisiert Serializer Saiten irgendeine Art von .toString () -Methode - das, das nicht bewusst von der Art der einzelnen Mitglieder ist und so umschließt alles in „“

.

Siehe Erstellen von JSON-Arrays in Boost Property Trees für mehr über dieses Problem.

ich am Ende eine andere Funktion meiner utils Aufsummierung dieses Problem zu lösen:

#include <string>
#include <regex>
#include <boost/property_tree/json_parser.hpp>

namespace bpt = boost::property_tree;
typedef bpt::ptree JSON;
namespace boost { namespace property_tree {
    inline void write_jsonEx(const std::string & path, const JSON & ptree)
    {
        std::ostringstream oss;
        bpt::write_json(oss, ptree);
        std::regex reg("\\\"([0-9]+\\.{0,1}[0-9]*)\\\"");
        std::string result = std::regex_replace(oss.str(), reg, "$1");

        std::ofstream file;
        file.open(path);
        file << result;
        file.close();
    }
} }

Ich hoffe, das hilft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top