c++jsonboostboost-propertytree

Read & Parse a JSON file c++ BOOST


As there is a lot of questions already on this, I am kind of apprehensive about asking... but

I've looked at many different Questions and nothing from any of them is working for me. I have this code as my attempt but it doesn't work:

#include "boost/property_tree/ptree.hpp"
#include "boost/property_tree/json_parser.hpp"
using namespace boost::property_tree;
...
std::ifstream jsonFile("test_file.json");
if (!jsonFile){
    std::cerr << "Error opening file\n";
    return -1;
}
ptree pt;
json_parser::read_json(jsonFile, pt);
for (auto& array_element : pt) {
    for (auto& property : array_element.second) {
        std::cout << property.first << " = " << property.second.get_value<std::string>() << "\n";
    }
}

Its contents are in the following format:

[{"number": 1234,"string": "hello world"}, {"number": 5678,"string": "foo bar"}, ... etc }]

I can't get it to read out the 1234 and then the hello world. Infact, it just does nothing. How can I read out from my .JSON file?


Solution

  • I'm not completely sure what the problem is. It seems to work (once you make the JSON valid):

    UPDATE: Boost JSON

    Boost 1.75.0 introduced Boost JSON, far superior way to actually deal with Json: Live On Wandbox

    #include <boost/json.hpp>
    #include <boost/json/src.hpp>
    #include <iostream>
    #include <iterator>
    #include <fstream>
    namespace json = boost::json;
    
    struct Rec {
        int64_t number;
        std::string string;
    
        friend Rec tag_invoke(json::value_to_tag<Rec>, json::value const& v) {
            auto& o = v.as_object();
            return {
                o.at("number").as_int64(),
                value_to<std::string>(o.at("string")),
            };
        }
    
        friend void tag_invoke(json::value_from_tag, json::value& v, Rec const& rec)
        {
            v = json::object{
                {"number", rec.number},
                {"string", rec.string},
            };
        }
    };
    
    int main() {
        std::ifstream ifs("input.txt");
        std::string   input(std::istreambuf_iterator<char>(ifs), {});
    
        using Recs = std::vector<Rec>;
        Recs recs  = value_to<std::vector<Rec>>(json::parse(input));
    
        for (auto& [n, s] : recs) {
            std::cout << "Rec { " << n << ", " << std::quoted(s) << " }\n";
    
            // some frivolous changes:
            n *= 2;
            reverse(begin(s), end(s));
        }
    
        std::cout << "Modified json: " << json::value_from(recs) << "\n";
    }
    

    Printing

    Rec { 1234, "hello world" }
    Rec { 5678, "foo bar" }
    Modified json: [{"number":2468,"string":"dlrow olleh"},{"number":11356,"string":"rab oof"}]
    

    Live On Coliru

    #include "boost/property_tree/ptree.hpp"
    #include "boost/property_tree/json_parser.hpp"
    
    int main() {
        using boost::property_tree::ptree;
    
        std::ifstream jsonFile("input.txt");
    
        ptree pt;
        read_json(jsonFile, pt);
    
        for (auto & array_element: pt) {
            for (auto & property: array_element.second) {
                std::cout << property.first << " = " << property.second.get_value < std::string > () << "\n";
            }
        }
    }
    

    With input.txt containing:

    [{"number": 1234, "string": "hello world"},{"number": 5678, "string": "foo bar"}]
    

    Prints

    number = 1234
    string = hello world
    number = 5678
    string = foo bar