// https://www.boost.org/doc/libs/1_92_0/libs/json/doc/html/json/conversion.html

#include <boost/json.hpp>

#include <cassert>
#include <iostream>
#include <string>
#include <vector>

struct package
{
    std::string name;
    std::string version;
    std::vector<int> bugs;
};

void tag_invoke(const boost::json::value_from_tag &, boost::json::value &jv, const package &p)
{
    jv = { { "name", p.name }, { "version", p.version },
           { "bugs", boost::json::value_from(p.bugs) } };
}

package tag_invoke(const boost::json::value_to_tag<package> &, const boost::json::value &jv)
{
    const boost::json::object &obj = jv.as_object();
    return package{ boost::json::value_to<std::string>(obj.at("name")),
                    boost::json::value_to<std::string>(obj.at("version")),
                    boost::json::value_to<std::vector<int> >(obj.at("bugs")) };
}

int main()
{
    const package p{ "boost1.92", "1.92.0-1", { 1001, 1002, 1003 } };

    const boost::json::value jv = boost::json::value_from(p);
    std::cout << "serialised: " << boost::json::serialize(jv) << std::endl;

    const package back = boost::json::value_to<package>(jv);
    assert(back.name == p.name);
    assert(back.version == p.version);
    assert(back.bugs == p.bugs);

    // Incremental parsing with the stream parser
    boost::json::stream_parser sp;
    boost::system::error_code ec;
    sp.write("[1, 2,", ec);
    assert(!ec);
    sp.write(" 3]", ec);
    assert(!ec);
    sp.finish(ec);
    assert(!ec);

    const boost::json::value arr = sp.release();
    std::cout << "stream parsed: " << boost::json::serialize(arr) << std::endl;
    assert(arr.as_array().size() == 3);

    return 0;
}
