programing

C++ 클래스의 JSON으로의 변환

iphone6s 2023. 3. 28. 21:20
반응형

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

JSON을 만들기 위해 몇 가지 C++ 라이브러리를 조사했는데 모두 매우 복잡한 것 같습니다.Javascript와 것을 JSON.stringify(object), 지도에는 다른 지도, 벡터, 목록, 문자열, 숫자 및 부울이 포함될 수 있습니다.

어떻게 하면 가장 좋은 방법일까요?

도와주셔서 고마워요.

편집

다음을 조사했습니다.

json spirit, jsoncpp, zoolib, JOST, CAJUN, libjson, nosjob, jsonBox, jsonme--

아래 답변과 같이 별도의 JSON 오브젝트를 작성하여 JSON으로 변환할 수 있는 것으로 알고 있습니다.표준 컬렉션에 저장하여 변환하고 싶습니다.

편집 2

좋아요, C++의 반성이 부족하기 때문에 불가능한 것 같기 때문에 수업을 연재하는 생각은 그만두세요.

std:maps, std::vectors, std:lists, 숫자, 문자열 및 bools를 포함하는 std::map을 JSON으로 변환하려면 데이터 유형을 변경하거나 데이터를 새 데이터 형식으로 복사하지 않아도 됩니다.

감사해요.

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" );
os.write( addr_obj, os, pretty_print );
os.close();

출력:

{
    "house_number" : 42,
    "road" : "East Street",
    "town" : "Newtown"
}

먼저 json_map_demo.cpp를 사용하는 것이 좋습니다.

이 문제는 정상적인 C++ JSON 라이브러리에서 해결할 수 있지만, 이 질문에서 언급한 ThorsSerializer명백히 Nosjob을 제외하고 그렇지 않은 것은 유감입니다.

에는 Java와 「C++」 타입에 으로 주석을 합니다.
(Thors Serializer 뉴뉴 ( ( )

#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++는 반사가 없기 때문에그리고 회원에게 공개 회원 레벨을 사용하거나 친구 클래스를 사용하는 방법을 제공해야 합니다.

그리고 나중에는 이렇게 하면 됩니다.

문자열 결과 = acml::json::syslog(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으로 표시하시겠습니까, 아니면 객체를 표시하시겠습니까?(이 예에서는 클래스를 나타내고 있습니다만, 맵이라고 말하고 있습니다).지도를 보려면 이 라이브러리 - JSON Spirit을 참조하십시오.

객체의 경우:(매우 제한된 RTI를 제외하고) C++에서는 리플렉션이 지원되지 않으므로 시리얼화를 위한 "원클릭" 솔루션도 없습니다.어떤 솔루션에서도 시리얼화 및 시리얼화 해제(비공개 데이터의 시리얼화 여부에 따라 다름)하는 클래스에 긴밀하게 결합된 추가 코드를 작성해야 합니다.

시리얼(http://uscilab.github.io/cereal/))을 본 적이 있습니까?C++ 를 사용해 JSON 와의 시리얼화를 실시하기 위한 JSON 아카이브가 있습니다.

(시리얼의) 오버헤드가 최소인 예는 SO에서 찾을 수 있습니다.https://stackoverflow.com/a/22587527/255635

저는 https://github.com/beached/daw_json_link의 저자입니다.C++는 지금 반사가 없기 때문에, 심플한 것을 없애면 좋을 것 같습니다.그러나 단순한 선언적 매핑을 정의함으로써 JSON Link는 유형에 대해 유형 체크 파서를 제공합니다.예를 들어 지정한 클래스는 다음과 같이 매핑할 수 있습니다.

    class Example {  
      std::string string;  
      std::map<std::string, std:string> map;  
      std::vector<int> vector;  
    };
        
    namespace daw::json {
      template<> 
      struct json_data_contract<Example> {
        using type = json_member_list<
          json_link<"string", std::string>, 
          json_link<"map", std::map<std::string, std::string>>
          json_link<"vector", std::vector<int>>>;
        
        static inline auto to_json_data( Example const & v ) {
          return std::forward_as_tuple( v.string, v.map, v.vector );
        }
      };
    }

매핑은 서부터 다른 안에 매핑을 '어리다'로 할 수 .json_class<"Name", Example>하는 건 '연재하다'의 일 뿐이에요auto json_document = daw::json::to_json( MyExampleValue ) 해석하기 .daw::json::from_json<Example>( json_document );라이브러리의 장점은 사용자 유형에 맞는 커스텀 파서를 생성하고 데이터를 구문 분석할 때 유형 검사를 수행하는 것입니다.

이는 사용자 정의 사전에서 수동으로 키와 값을 만들거나 유지 관리할 필요 없이 기존 클래스/구조의 멤버 변수를 선택적으로 저장할 수 있는 매우 가벼운 솔루션입니다.nlohmann json(부스트 또는 기타 무거운 라이브러리 없음)만 사용합니다.

nlohmann::json을 사용하면 임의의 유형의 변환을 할 수 있습니다.상세한 것에 대하여는, https://nlohmann.github.io/json/features/arbitrary_types/ 를 참조해 주세요.

코드:

// example.cc
#include <string>
#include <iostream>
#include <map>
#include <vector>

#include "third_party/nlohmann/json.hpp"

struct Example {
    std::string name;
    std::map<std::string, int> dict;
    std::vector<int> vec;
    std::string this_member_is_not_part_of_the_json;
};

// Use NLOHMANN_DEFINE_TYPE_INTRUSIVE if your members are private.
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Example,
    name,
    dict,
    vec);

int main() {
  Example example;
  example.name = "Example";
  example.dict = {{"AnyKey", 42}};
  example.vec = {1, 2, 3};

  nlohmann::json json;
  to_json(json, example);  // "generated" function

  std::cout << json.dump(1) << std::endl;

  return 0;
}

코드를 컴파일합니다.

g++ -I third_party/nlohmann/ example.cc -o example

../example★★★★

{
 "dict": {
  "AnyKey": 42
 },
 "name": "Example",
 "vec": [
  1,
  2,
  3
 ]
}

설명:

: ★★★★★★★★★★★★★★★★★★★★★★★★★★★」NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE 정의 에서, 은 함수 "이러면 안 돼요"를 합니다.to_json(...)같은 네임스페이스에 있습니다.

  • json.dump(1)조손

저는 이 작업을 수행할 수 있는 실험 라이브러리를 작성했습니다만, 클래스 구조와 계층에 대한 외부 설명이 필요합니다.GCCXML을 사용하여 시리얼화 디시리얼라이제이션에 사용되는 xml 사전을 구축합니다.

http://code.google.com/p/cjson/

지금은 기본형(int, float double), 기본형, 클래스, 상속된 멤버 등에 대한 포인터 등을 다룰 수 있는 실험 프로젝트입니다.기본 std::vector ans std::map serialization을 구현하고 std::string 인스턴스도 구현합니다.

구현에 대한 자세한 내용은 여기를 참조하십시오.

Boost를 사용할 수 있습니다.속성 트리

#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

namespace pt = boost::property_tree;

int main() {
    // Create an empty property tree object.
    pt::ptree tree;

    // Put a string value into the tree.
    tree.put("string", "the-string-value");

    // Put a map object into the tree.
    pt::ptree child1;
    std::map<std::string, std::string> map = {{"key1", "val1"},
                                              {"key2", "val2"}};
    for (auto &p : map) {
        child1.add(p.first, p.second);
    }
    tree.add_child("map", child1);

    // Put a vector of numbers into the tree
    pt::ptree child2;
    std::vector<int> vector = {1, 2, 3, 4};
    for (auto &v : vector) {
        pt::ptree item;
        item.put("", v);
        child2.push_back(std::make_pair("", item));
    }
    tree.add_child("vector", child2);

    // Write property tree to JSON file
    pt::write_json("output.json", tree);

    return 0;
}

출력:

{
    "string": "the-string-value",
    "map": {
        "key1": "val1",
        "key2": "val2"
    },
    "vector": [
        "1",
        "2",
        "3",
        "4"
    ]
}

RareCpp에서는 리플렉션 구현 위에 매우 효과적인 JSON 라이브러리를 만들었습니다.C++17용으로 작성되었으며 Visual Studios, g++, Clang과 함께 사용할 수 있습니다.라이브러리는 헤더 전용입니다.즉, 이 라이브러리를 사용하려면 reflect 헤더와 json 헤더만 프로젝트에 복사하면 됩니다.

JSON 라이브러리는 REFLET 매크로에서 필드를 한 번만 나열하면 됩니다.이러한 매크로에서는 읽기 또는 쓰기에 적합한 JSON 출력 표현을 자동으로 식별하고 반사된 필드뿐만 아니라 어레이, STL 컨테이너, 참조, 포인터 등을 재귀적으로 통과할 수 있습니다.

struct MyOtherObject { int myOtherInt; REFLECT(MyOtherObject, myOtherInt) };
struct MyObject
{
    int myInt;
    std::string myString;
    MyOtherObject myOtherObject;
    std::vector<int> myIntCollection;

    REFLECT(MyObject, myInt, myString, myOtherObject, myIntCollection)
};

int main()
{
    MyObject myObject = {};
    std::cout << "Enter MyObject:" << std::endl;
    std::cin >> Json::in(myObject);
    std::cout << std::endl << std::endl << "You entered:" << std::endl;
    std::cout << Json::pretty(myObject);
}

상기의 내용은 다음과 같이 실행할 수 있습니다.

Enter MyObject:
{
  "myInt": 1337, "myString": "stringy", "myIntCollection": [2,4,6],
  "myOtherObject": {
    "myOtherInt": 9001
  }
}


You entered:
{
  "myInt": 1337,
  "myString": "stringy",
  "myOtherObject": {
    "myOtherInt": 9001
  },
  "myIntCollection": [ 2, 4, 6 ]
}

필드에 주석을 달아 JSON 표현에서 다른 이름을 지정하거나 문자열로 강제 지정하는 등의 작업을 수행할 수도 있습니다.

struct Point
{
    NOTE(latitude, Json::Name{"lat"})
    double latitude;

    NOTE(longitude, Json::Name{"long"})
    double longitude;

    REFLECT(Point, latitude, longitude)
};

자세한 예는 여기를 참조해 주세요.슈퍼 클래스 캡처, 컴파일 시 알려지지 않은 JSON 읽기, 트래버스 및 쓰기 지원, 특정 필드 또는 유형에 대한 JSON 표현 추가 커스터마이즈 등 다양한 기능이 있습니다.

python 스크립트는 각 json 속성에 대해 하나의 멤버로 c++ 포드 클래스를 생성합니다.

당신은 정반대의 것을 원하지만 로드와 저장을 모두 하는 매핑 클래스를 생성하는 것은 간단하다.

생성된 코드는 외부 json 파서 라이브러리에 의존합니다.

질문이 여전히 실제인 경우 JSON 표현과 c++ 구조체 간의 데이터 변환을 위한 작은 헤더 전용 도우미인 json_dto 라이브러리를 살펴봅니다.

예를 들어 다음과 같은 구조를 갖습니다.

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 문자열을 지정하면 구조체로 변환할 수 있습니다.

언급URL : https://stackoverflow.com/questions/8220130/converting-c-class-to-json

반응형