본문 바로가기

운동하는 개발자/c++

c++ boost를 이용한 json 파싱 (boost::json & boost::property_tree)

728x90

boost library를 사용하여 json 데이터를 파싱 하는 법을 찾아보니 두 가지 라이브러리가 있었다
둘 다 해더만 추가해서 간단하게 사용하는 방식이였고 자료는 property_tree 이게 압도적으로 많았고 boost::json은 잘 안 쓰이는지 예제 코드가 많이 없었다 특히 array내부의 값을 획득하는 예제를 찾는데 힘들었다

왜 동일한 기능의 라이브러리가 두가지로 나눠져 있나 궁금하여 찾아보았다
boost::property_tree가 먼저 나왔으며 이는 트리구조로 JSON뿐만 아니라 XML, INI를 읽을 수 있다 정확히는 JSON을 파싱 하는 용도라기보단 트리구조로 다양한 형식의 데이터를 처리하기 위한 라이브러리이다

다음 boost:json의 경우에는 목적 자체가 JSON데이터를 처리하기 위해 만들어진 라이브러리이기에 JSON데이터를 파싱하고 생성하는데 다양한 기능들을 제공하고 조금 더 간결하다

자 그럼 직접 써보자

1) boost::property_tree

    #include <boost/property_tree/json_parser.hpp>
    #include <iostream>
    
    //파싱할 데이터
    std::string val = R"({
        "tag": "productlist",
        "body" : [
            {
                "product": "ball",
                "version" : "3.2.4.25"
            },
            {
                "product": "calamari",
                "version" : "1.3.1"
            }
        ]
    })";
    
    //데이터 처리
    boost::property_tree::ptree jsontree;
    std::stringstream ss(val);
    boost::property_tree::read_json(ss, jsontree);

    //tag값 획득
    std::string tag = jsontree.get<std::string>("tag", "");
    std::cout << tag << "\n";

	//array내에 있는 값 획득
    std::vector<std::pair<std::string, std::string>> bodys;	
    for (boost::property_tree::ptree::value_type& body : jsontree.get_child("body")) {
        for (boost::property_tree::ptree::value_type product : body.second) {
            std::cout << product.first << ":" << product.second.data() << "\n";        
            bodys.push_back(std::make_pair(product.first, product.second.data()));
        }              
    }

 

2) boost::json

#include <boost/json.hpp>
#include <iostream>

//파싱할 데이터
std::string val = R"({
    "tag": "productlist",
    "body" : [
        {
            "product": "ball",
            "version" : "3.2.4.25"
        },
        {
            "product": "calamari",
            "version" : "1.3.1"
        }
    ]
})";

//데이터 변환
boost::json::value jv = boost::json::parse(val);

//tag값 획득
boost::json::object& jobj = jv.as_object();   
std::cout << boost::json::value_to<std::string>(jobj.at("tag")) << "\n";

//array 내부의 값 순환하며 획득
for (const auto& item : jobj.at("body").as_array()) {
    std::cout << "  product: " << item.at("product").as_string() << std::endl;
    std::cout << "  version: " << item.at("version").as_string() << std::endl;
}

 

간단한 구문 파싱이였기에 딱히 뭐가 더 낫다는 생각은 들지 않았다

나중에 더 복잡하고 대용량을 처리하는 분들은 실험이 좀 필요할 것 같다


 

728x90