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

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

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

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

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

ВОПРОСЫ:

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

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


person akshay dhule    schedule 22.01.2019    source источник
comment
Библиотека Nlohmann json упрощает эту задачу: github.com/ nlohmann/json/blob/develop/   -  person Shawn    schedule 23.01.2019
comment
посмотрите на это: stackoverflow.com/questions/54256758/   -  person xyz347    schedule 23.01.2019
comment
Вы проверяете ThorsSerializer   -  person Martin York    schedule 16.03.2019
comment
Поскольку Майло некоторое время не обновлял свою производительность Json, я поработал над ней здесь: github.com/Loki -Astari/JsonBenchmark Результаты производительности (созданы Трэвисом) mac linux   -  person Martin York    schedule 16.03.2019


Ответы (2)


Есть ли эквивалент в 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 в main выполняется просто:

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}]
person Martin York    schedule 15.03.2019

jsoncons, nlohmann и ThorsSerializer поддерживают преобразование между объектами JSON и C++. Примеры с jsoncons и nlohmann показаны ниже, у Мартина Йорка есть один для ThorsSerializer в отдельной публикации. Последнее, на мой взгляд, очень красивое и, безусловно, выигрывает приз за краткость. В духе цитаты Оскара Уайльда о том, что «подражание — самая искренняя форма лести», я представил макрос JSONCONS_ALL_MEMBER_TRAITS для 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_ALL_MEMBER_TRAITS(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"
    }
]
person Daniel    schedule 15.03.2019