Преобразование класса C++ в JSON
Я хотел бы создать строку JSON, содержащую переменные экземпляра моего класса.
например,
class Example {
std::string string;
std::map<std::string, std:string> map;
std::vector<int> vector;
};
станет:
{
"string":"the-string-value",
"map": {
"key1":"val1",
"key2":"val2"
},
"vector":[1,2,3,4]
}
Я просмотрел несколько библиотек C++ для создания JSON, и все они кажутся невероятно сложными. Я бы хотел что-то похожее на Javascript JSON.stringify(object). Другими словами, просто передайте ему std::map и получите строку. Карта может содержать другие карты, векторы, списки, строки, числа и т. д тип bool.
какой самый хороший способ сделать это?
Спасибо за вашу помощь.
Edit
я рассмотрел следующее:
JSON с духом, jsoncpp, zoolib, Йост, КЕЙДЖИНСКАЯ позволяет использовать, nosjob, JsonBox, jsonme--
что я понимаю, я могу построить отдельный объект JSON, как в ответе ниже, и преобразовать в JSON я хотел бы иметь возможность хранить свои вещи в стандартных коллекциях и конвертировать.
Edit 2
хорошо, откажитесь от идеи сериализации класса, поскольку кажется, что это невозможно с отсутствием отражения C++.
есть ли хороший способ конвертировать std:: map, содержащий std: maps, std:: vectors, std:: lists, numbers, strings и bools в JSON без необходимости изменять типы данных или копировать данные в новый тип данных?
спасибо.
8 ответов:
JSON Spirit позволит вам сделать это вот так:
Object addr_obj; addr_obj.push_back( Pair( "house_number", 42 ) ); addr_obj.push_back( Pair( "road", "East Street" ) ); addr_obj.push_back( Pair( "town", "Newtown" ) ); ofstream os( "address.txt" ); write( addr_obj, os, pretty_print ); os.close();выход:
{ "house_number" : 42, "road" : "East Street", "town" : "Newtown" }The json_map_demo.cpp было бы неплохо начать, я полагаю.
любая хорошая библиотека C++ JSON должна делать это, и грустно видеть, что они этого не делают-за исключением ThorsSerializer и, видимо,Nosjob как уже упоминалось в этой вопрос.
конечно, C++ не имеет отражения, как Java, поэтому вы должны явно аннотировать свои типы:
(скопировано из документации ThorsSerializer)#include "ThorSerialize/JsonThor.h" #include "ThorSerialize/SerUtil.h" #include <map> #include <vector> #include <string> #include <iostream> class Example { std::string string; std::map<std::string, std::string> map; std::vector<int> vector; // Allow access to the class by the serialization library. friend class ThorsAnvil::Serialize::Traits<Example>; public: Example(std::string const& s, std::map<std::string, std::string> const& m, std::vector<int> const& v) : string(s), map(m), vector(v) {} }; // Define what members need to be serilizable ThorsAnvil_MakeTrait(Example, string, map, vector);пример Использование:
int main() { using ThorsAnvil::Serialize::jsonExport; using ThorsAnvil::Serialize::jsonImport; Example e1 {"Some Text", {{"ace", "the best"}, {"king", "second best"}}, {1 ,2 ,3, 4}}; // Simply serialize object to json using a stream. std::cout << jsonExport(e1) << "\n"; // Deserialize json text from a stream into object. std::cin >> jsonImport(e1); }работает:
{ "string": "Some Text", "map": { "ace": "the best", "king": "second best" }, "vector": [ 1, 2, 3, 4] }вы не можете сделать лучше, чем это в C++.
Я написал библиотеку, которая предназначена для решения вашей проблемы. Однако это очень новый проект, недостаточно стабильный. Не стесняйтесь взглянуть, Домашняя страница здесь::
https://github.com/Mizuchi/acml
в вашем примере, вы должны добавить одну строку:
ACML_REGISTER(Example, ,(string)(map)(vector));чтобы сообщить библиотеке, какой член вы хотите сбросить. Так как C++ не имеют отражения. И вы должны дать способ доступа к члену, либо использовать открытый уровень члена или использовать класс друзей.
а позже вам просто нужно сделать sth вот так:
string result = acml:: json::dumps(any_object);
станет::
{ "string": "the-string-value", "map": { "key1": "val1", "key2": "val2" }, "vector": { "type": "std::vector", "size": "4", "0": "1", "1": "2", "2": "3", "3": "4" } }Как вы видите, массив JSON еще не реализован. И теперь все становится струной.
вы хотите JSON-ify карту или объект? (ваш пример показывает класс, но вы говорите карту). Для карты, проверьте эту библиотеку - JSON Spirit.
для объектов: в C++ нет поддержки отражения (кроме очень ограниченного RTTI), поэтому для сериализации также нет решения "одним щелчком мыши". Любое решение потребует от вас написать дополнительный, возможно, тесно связанный код для класса, который вы хотите сериализовать и де-сериализовать (это зависит от того, хотите ли вы сериализация непубличных данных).
вы смотрели на хлопья (http://uscilab.github.io/cereal/) ? Он имеет архивы JSON для сериализации в / из JSON с использованием C++.
пример с минимальными накладными расходами (из зерновых) можно найти здесь на SO:https://stackoverflow.com/a/22587527/255635
Я написал экспериментальную библиотеку, которая может выполнять эту работу, но она требует внешнего описания структур классов и иерархии. Он использует GCCXML для создания XML-словаря, используемого для сериализации де-сериализации:
http://code.google.com/p/cjson/
Это на данный момент экспериментальный проект, который может иметь дело с фундаментальными типами (int, float double), указателями на фундаментальные типы, классы, наследуемые члены и т. д... Он реализует базовая сериализация std::vector ans std::map, а также экземпляры std::string.
Смотрите подробности реализации здесь
этой скрипт python генерирует классы C++ pod с одним членом для каждого свойства json
вы хотите совершенно противоположную вещь, но тривиально генерировать класс отображения, который выполняет как загрузку, так и сохранение
сгенерированный код опирается на внешнюю библиотеку парсеров json
Если вопрос все еще актуален, то посмотрите на json_dto библиотека, небольшой помощник только для заголовка для преобразования данных между представлением JSON и структурами c++.
например, имея следующие структуры:
struct message_source_t { // Worker thread. std::int32_t m_thread_id; // Sender. std::string m_subsystem; }; struct message_t { // Who sent a message. message_source_t m_from; // When the message was sent (unixtime). std::tm m_when; // Message text. std::string m_text; };С помощью json_dto вы можете создать следующий JSON:
{ "from" : { "thread_id" : 4242, "sybsystem" : "json_dto" }, "when" : "2016.09.28 19:55:00", "text" : "Hello world!" }и учитывая такую строку JSON, вы можете преобразовать ее в структуры.
Comments