Cpp: анализатор JSON в Cpp, обеспечивающий поддержку функции сериализации / десериализации, преобразования объектов JSON в определяемые пользователем классы? - PullRequest
0 голосов
/ 23 января 2019

Я работаю над собственной разработкой на C ++ и ищу парсер JSON, который может обрабатывать сложные JSON-файлы и преобразовывать их в объекты классов.

  1. Я просмотрел собственные тесты для анализаторов JSON , доступные на C ++, и пришел к выводу, что RapidJSON популярен и лучше всего подходит для обработки времени и размера.

  2. Мое требование - преобразовать объекты JSON в определенные пользователем классы и наоборот.

  3. Джексон имеет Objectmapper класс, который предоставляет функциональные возможности для чтения и записи JSON, как в базовые POJO (простые старые объекты Java), так и из универсальной модели дерева JSON (JsonNode), а также связанную функциональность для выполненияпреобразования.

ВОПРОСЫ:

  1. Есть ли эквивалент в RapidJSON или другом анализаторе JSON, который позволяет нам настраивать функцию сериализации и десериализации (например, библиотека Jackson JAVAтакое настраиваемый процесс сериализации и десериализации, преобразовывающий объекты JSON в классы Java?Есть ли единственный способ создать свой собственный сериализатор для преобразования в наши пользовательские классы?

ПРИМЕЧАНИЕ. Я просмотрел несколько постов по stackoverflow и не нашел ни одного ответа на него.

Ответы [ 2 ]

0 голосов
/ 16 марта 2019

Существует ли в RapidJSON или другом анализаторе JSON аналог, позволяющий нам настраивать функцию сериализации и десериализации (например, библиотека JAVA Джексона - это настраиваемый процесс сериализации и десериализации, конвертирующий объекты JSON в классы Java)?

Я думаю, что ThorsSerializer сделает свою работу.
Все, что вам нужно сделать, это объявить через ThorsAnvil_MakeTrait(), какие поля в классе сериализуемы (см. Ниже).

Если нет, как правильно обойти это? Есть ли единственный способ создать собственный сериализатор для преобразования в наши пользовательские классы?

Вы можете использовать RapidJSON (или несколько других библиотек), но вам нужно написать код клиента для преобразования объектов JSON, сгенерированных библиотекой, в ваши собственные объекты. Это не очень сложно.

Другим недостатком большинства библиотек является то, что они фактически создают полное представление данных в JSON-подобных объектах, и вам необходимо скопировать данные в свою структуру. Для небольших объектов это не проблема, но для более сложных конструкций это может занять некоторое пространство. ThorsSerializer полностью избегает этого и копирует данные непосредственно в ваши структуры: см. просмотр используемой памяти.

Используя тот же пример, что и @ Daniel
Использование ThorsSerializer: https://github.com/Loki-Astari/ThorsSerializer
Примечание: я автор.

#include <string>

const std::string s = R"(
[
    {
        "author" : "Haruki Murakami",
        "title" : "Kafka on the Shore",
        "price" : 25.17
    },
    {
        "author" : "Charles Bukowski",
        "title" : "Pulp",
        "price" : 22.48
    }
]
)";

namespace ns {
    struct book
    {   
        std::string author;
        std::string title;
        double price;
    };  
} // namespace ns


#include <iostream>
#include "ThorSerialize/Traits.h"   // for ThorsAnvil_MakeTrait
#include "ThorSerialize/SerUtil.h"  // Has definitions for all STL types.
#include "ThorSerialize/JsonThor.h" // JSON version: There is also YAML


ThorsAnvil_MakeTrait(ns::book, author, title, price);

Тогда читать / писать json в основном просто:

int main()
{
     using ThorsAnvil::Serialize::jsonExport;
     using ThorsAnvil::Serialize::jsonImport;


     std::stringstream   stream(s);

     ns::book                   book;
     std::vector<ns::book>      allBooks;
     stream >> jsonImport(allBooks);

     std::cout << jsonExport(allBooks)
               << "\n\n"
               << jsonExport(allBooks, ThorsAnvil::Serialize::PrinterInterface::OutputType::Stream)
               << "\n\n";
}

Чтобы построить:

> g++ -std=c++14 main.cpp -lThorSerialize17

Выход:

> ./a.out 
[ 
    { 
        "author": "Haruki Murakami", 
        "title": "Kafka on the Shore", 
        "price": 25.17
    }, 
    { 
        "author": "Charles Bukowski", 
        "title": "Pulp", 
        "price": 22.48
    }]

[{"author":"Haruki Murakami","title":"Kafka on the Shore","price":25.17},{"author":"Charles Bukowski","title":"Pulp","price":22.48}]
0 голосов
/ 15 марта 2019

jsoncons , nlohmann и ThorsSerializer все поддерживают преобразование между объектами JSON и C ++.Примеры с jsoncons и nlohmann показаны ниже, у Мартина Йорка есть один для его ThorsSerializer в отдельной публикации.Последнее, на мой взгляд, очень приятно, и, безусловно, выигрывает приз за краткость.В духе цитаты Оскара Уайльда, что «имитация является самой искренней формой лести», я представил макрос JSONCONS_MEMBER_TRAITS_DECL в jsoncons и соответственно изменил этот пример.

Рассмотрим

const std::string s = R"(
[
    {
        "author" : "Haruki Murakami",
        "title" : "Kafka on the Shore",
        "price" : 25.17
    },
    {
        "author" : "Charles Bukowski",
        "title" : "Pulp",
        "price" : 22.48
    }
]
)";

namespace ns {
    struct book
    {
        std::string author;
        std::string title;
        double price;
    };
} // namespace ns

Использование jsoncons для преобразования между s и std::vector<ns::book>:

#include <jsoncons/json.hpp>

namespace jc = jsoncons;

// Declare the traits. Specify which data members need to be serialized.
JSONCONS_MEMBER_TRAITS_DECL(ns::book,author,title,price);

int main()
{
    std::vector<ns::book> book_list = jc::decode_json<std::vector<ns::book>>(s);

    std::cout << "(1)\n";
    for (const auto& item : book_list)
    {
        std::cout << item.author << ", " 
                  << item.title << ", " 
                  << item.price << "\n";
    }

    std::cout << "\n(2)\n";
    jc::encode_json(book_list, std::cout, jc::indenting::indent);
    std::cout << "\n\n";
}

Вывод:

(1)
Haruki Murakami, Kafka on the Shore, 25.17
Charles Bukowski, Pulp, 22.48

(2)
[
    {
        "author": "Haruki Murakami",
        "price": 25.17,
        "title": "Kafka on the Shore"
    },
    {
        "author": "Charles Bukowski",
        "price": 22.48,
        "title": "Pulp"
    }
]

Использование nlohmann для преобразования между s и std::vector<ns::book>:

#include <nlohmann/json.hpp>
#include <iomanip>

namespace nh = nlohmann;

// Provide from_json and to_json functions in the same namespace as your type   
namespace ns {
    void from_json(const nh::json& j, ns::book& val) 
    {
        j.at("author").get_to(val.author);
        j.at("title").get_to(val.title);
        j.at("price").get_to(val.price);
    }

    void to_json(nh::json& j, const ns::book& val) 
    {
        j["author"] = val.author;
        j["title"] = val.title;
        j["price"] = val.price;
    }
} // namespace ns

int main()
{
    nh::json j = nh::json::parse(s);

    std::vector<ns::book> book_list = j.get<std::vector<ns::book>>();
    std::cout << "\n(1)\n";
    for (const auto& item : book_list)
    {
        std::cout << item.author << ", " 
                  << item.title << ", " 
                  << item.price << "\n";
    }

    std::cout << "\n(2)\n";
    nh::json j2 = book_list;
    std::cout << std::setw(4) << j2 << "\n\n";
}

Вывод:

(1)
Haruki Murakami, Kafka on the Shore, 25.17
Charles Bukowski, Pulp, 22.48

(2)
[
    {
        "author": "Haruki Murakami",
        "price": 25.17,
        "title": "Kafka on the Shore"
    },
    {
        "author": "Charles Bukowski",
        "price": 22.48,
        "title": "Pulp"
    }
]
...