programing

속성 트리를 사용하여 Boost에서 JSON 어레이 생성

goodsources 2023. 2. 25. 20:57
반응형

속성 트리를 사용하여 Boost에서 JSON 어레이 생성

부스트 속성 트리를 사용하여 JSON 어레이를 생성하려고 합니다.

문서에는 다음과 같이 기재되어 있습니다.JSON 어레이는 노드에 매핑되어 있습니다.각 요소는 이름이 비어 있는 하위 노드입니다."

빈 , 그에 전화하겠습니다write_json(...)어레이를 꺼냅니다.그러나 문서에는 이름 없는 하위 노드를 만드는 방법은 나와 있지 않습니다.는 는 i i는노노 i i i i i.ptree.add_child("", value)과 같은 결과를낳습니다: ,, 음, 다, 다, 다, 다, 니, 니, ,, ,, ,, ,.

Assertion `!p.empty() && "Empty path not allowed for put_child."' failed

이 문서에서는 이 점을 다루지 않는 것 같습니다.최소한 제가 알 수 있는 것은 아닙니다.누구 도와줄 사람?

심플한 어레이:

#include <boost/property_tree/ptree.hpp>
using boost::property_tree::ptree;

ptree pt;
ptree children;
ptree child1, child2, child3;

child1.put("", 1);
child2.put("", 2);
child3.put("", 3);

children.push_back(std::make_pair("", child1));
children.push_back(std::make_pair("", child2));
children.push_back(std::make_pair("", child3));

pt.add_child("MyArray", children);

write_json("test1.json", pt);

결과는 다음과 같습니다.

{
    "MyArray":
    [
        "1",
        "2",
        "3"
    ]
}

객체 위의 배열:

ptree pt;
ptree children;
ptree child1, child2, child3;


child1.put("childkeyA", 1);
child1.put("childkeyB", 2);

child2.put("childkeyA", 3);
child2.put("childkeyB", 4);

child3.put("childkeyA", 5);
child3.put("childkeyB", 6);

children.push_back(std::make_pair("", child1));
children.push_back(std::make_pair("", child2));
children.push_back(std::make_pair("", child3));

pt.put("testkey", "testvalue");
pt.add_child("MyArray", children);

write_json("test2.json", pt);

결과는 다음과 같습니다.

{
    "testkey": "testvalue",
    "MyArray":
    [
        {
            "childkeyA": "1",
            "childkeyB": "2"
        },
        {
            "childkeyA": "3",
            "childkeyB": "4"
        },
        {
            "childkeyA": "5",
            "childkeyB": "6"
        }
    ]
}

당신이 해야 할 일은 이 재미입니다.이건 기억에서 나온 건데, 난 이런 게 좋아.

boost::property_tree::ptree root;
boost::property_tree::ptree child1;
boost::property_tree::ptree child2;

// .. fill in children here with what you want
// ...

ptree.push_back( std::make_pair("", child1 ) );
ptree.push_back( std::make_pair("", child2 ) );

하지만 json 구문 분석과 쓰기에는 몇 가지 버그가 있습니다.그 중 몇 가지에 대해 버그 보고서를 제출했지만 응답이 없습니다.

편집: {"」로 잘못 일련화되는 것에 대한 우려에 대처하기 위해:"", ""}

이 문제는 어레이가 루트 요소인 경우에만 발생합니다.boost ptree writer는 모든 루트 요소를 개체로 취급하며 배열이나 값은 사용하지 않습니다.이는 boost/propert_tree/detail/json_parser_writer.hpp의 다음 행이 원인입니다.

else if (indent > 0 && pt.count(Str()) == pt.size())

"indent > 0 & &" 를 삭제하면 어레이를 올바르게 쓸 수 있습니다.

공간 절약이 마음에 들지 않으면 여기에 제공된 패치를 사용할 수 있습니다.

속성 트리를 사용하여 JSON 구조를 나타낼 때 유사한 문제가 발생했지만 해결하지 못했습니다.또, 이 메뉴얼에서는, 속성 트리가 타입 정보를 완전하게 서포트하고 있지 않습니다.

JSON 값은 값을 포함하는 노드에 매핑됩니다.그러나 모든 유형 정보는 손실됩니다. 숫자뿐만 아니라 리터럴 "null", "true" 및 "false"도 문자열 형식으로 매핑됩니다.

이것을 알고, 보다 완전한 JSON 실장 JSON Spirit으로 전환했습니다.이 라이브러리는 JSON 문법 구현에 Boost Spirit을 사용하며 어레이를 포함한 JSON을 완전히 지원합니다.

대체 C++ JSON 실장 사용을 권장합니다.

제 경우, 어느 정도 임의의 위치에 어레이를 추가하고 싶었기 때문에 Michael의 답변처럼 하위 트리를 만들고 어레이 요소를 채웁니다.

using boost::property_tree::ptree;

ptree targetTree;
ptree arrayChild;
ptree arrayElement;

//add array elements as desired, loop, whatever, for example
for(int i = 0; i < 3; i++)
{
  arrayElement.put_value(i);
  arrayChild.push_back(std::make_pair("",arrayElement))
}

자녀가 입력되면put_child()또는add_child()이렇게 전체 하위 트리를 대상 트리에 추가하는 기능...

targetTree.put_child(ptree::path_type("target.path.to.array"),arrayChild)

put_child 함수는 인수 경로와 트리를 사용하여 arrayChild를 타겟으로 "grapt"합니다.트리

현재boost 1.60.0, 아직 문제가 발생.

제공:Python 3회피책(Gist), 직후에 시스템화할 수 있습니다.boost::property_tree::write_json.

#!/usr/bin/env python3


def lex_leaf(lf: str):
    if lf.isdecimal():
        return int(lf)
    elif lf in ['True', 'true']:
        return True
    elif lf in ['False', 'false']:
        return False
    else:
        try:
            return float(lf)
        except ValueError:
            return lf

def lex_tree(j):
    tj = type(j)
    if tj == dict:
        for k, v in j.items():
            j[k] = lex_tree(v)
    elif tj == list:
        j = [lex_tree(l) for l in j]
    elif tj == str:
        j = lex_leaf(j)
    else:
        j = lex_leaf(j)
    return j


def lex_file(fn: str):
    import json
    with open(fn, "r") as fp:
        ji = json.load(fp)
    jo = lex_tree(ji)
    with open(fn, 'w') as fp:
        json.dump(jo, fp)


if __name__ == '__main__':
    import sys
    lex_file(sys.argv[1])

JSON을 C++로 하려면 Boost를 사용할 필요가 없습니다.라이브러리를 사용하면 JSON을 STL 컨테이너처럼 작동하는 퍼스트 클래스 데이터 유형으로 가져올 수 있습니다.

// Create JSON on the fly.
json j2 = {
  {"pi", 3.141},
  {"happy", true},
  {"name", "Niels"},
  {"nothing", nullptr},
  {"answer", {
    {"everything", 42}
  }},
  {"list", {1, 0, 2}},
  {"object", {
    {"currency", "USD"},
    {"value", 42.99}
  }}
};

// Or treat is as an STL container; create an array using push_back
json j;
j.push_back("foo");
j.push_back(1);
j.push_back(true);

// also use emplace_back
j.emplace_back(1.78);

// iterate the array
for (json::iterator it = j.begin(); it != j.end(); ++it) {
  std::cout << *it << '\n';
}

공식 문서와 위의 답변에 혼란스러웠습니다.아래는 제가 이해한 내용입니다.

속성 트리는 노드로 구성됩니다.
각 노드는 다음과 같습니다.

 struct ptree
    {
       map<key_name,value>          data;
       vector<pair<key_name,ptree>> children; 
    };

'put'으로 데이터에 'value'를 입력하려면
'push_back'을 가진 아이에게 'node'를 삽입하려면\

// Write 
    bt::ptree root;
    bt::ptree active;
    bt::ptree requested;
    bt::ptree n1, n2, n3;
        
    n1.put("name", "Mark");
    n1.put("age", 20);
    n1.put("job", "aaa");

    n2.put("name", "Rosie");
    n2.put("age", "19");
    n2.put("job", "bbb");

    n3.put("name", "sunwoo");
    n3.put("age", "10");
    n3.put("job", "ccc");

    active.push_back   ({ "",l1 });
    active.push_back   ({ "",l2 });
    requested.push_back({ "",l3 }); 
    root.push_back     ({"active", active});
    root.push_back     ({"requested", requested});

    bt::write_json("E:\\1.json", root);


    // READ
    bt::ptree root2;
    bt::ptree active2;
    bt::ptree requested2;
    bt::ptree r1, r2, r3;

    bt::read_json("E:\\1.json", root2);

    // loop children
    for (auto& [k,n] : root.get_child("active"))
    {       
        cout << n.get<string>("name", "unknown");
        cout << n.get<int>   ("age" , 11);
        cout << n.get<string>("job" , "man");
        cout << endl << flush;
    }

언급URL : https://stackoverflow.com/questions/2114466/creating-json-arrays-in-boost-using-property-trees

반응형