5

I am working with https://github.com/nlohmann/json and it works well. However I am finding difficulties to create the following json outout

 {
    "Id": 1,
    "Child": [
        {
            "Id": 2
        },
        {
            "Id": 3,
            "Child": [
                {
                  "Id" : 5
                },
                {
                  "Id" : 6
                }
            ]
        },
        {
            "Id": 4
        }
    ]
}

Every node must have an id and an array ("Child" element). Any child can recursively continue to have Id or Child. The json above is just an example. What I want is to create a chain between father and children node using nlohmann json.

Numbers 1, 2, 3, .... are picked up randomly. We don't care for now about those values.

Any idea how to create it?

Code so far

#include <iostream>
#include <string>
#include <vector>
#include "json.hpp"

using json = nlohmann::json;


struct json_node_t {

    int id;
    std::vector<json_node_t> child;
};


int main( int argc, char** argv) {

    json j;

    for( int i = 0; i < 3; i++) {

        json_node_t n;

        n.id = i;
        j["id"] = i;

        if ( i < 2 ) {

            j["child"].push_back(n);


        }


    }


    return 0;

}
2
  • How are we supposed to infer that 5 and 6 should be children of 3 and not, say, 2? This post has many of the same problems your last question (stackoverflow.com/questions/45882363/…) had. Commented Aug 25, 2017 at 14:47
  • I don't really care about the values of the id elements. I just want to find out how to create a recursive representation of data using nlohmann json Commented Aug 25, 2017 at 14:50

1 Answer 1

5

In order to serialize your own type, you need to implement a to_json function for that type.

#include <iostream>
#include <string>
#include <vector>
#include "json.hpp"

using namespace std;
using json = nlohmann::json;

struct json_node_t {
    int id;
    std::vector<json_node_t> child;
};

void to_json(json& j, const json_node_t& node) {
    j = {{"ID", node.id}};
    if (!node.child.empty())
        j.push_back({"children", node.child});
}

int main() {
    json_node_t node = {1, {{2, {}}, {3, {{5, {}}, {6, {}}}}, {4, {}}}};
    json j = node;

    cout << j.dump(2) << endl;
    return 0;
}

Output:

{
  "ID": 1,
  "children": [
    {
      "ID": 2
    },
    {
      "ID": 3,
      "children": [
        {
          "ID": 5
        },
        {
          "ID": 6
        }
      ]
    },
    {
      "ID": 4
    }
  ]
}

A couple of more ways to initialize json_node_t (all producing the same tree and the same output):

struct json_node_t {
    int id;
    std::vector<json_node_t> child;
    json_node_t(int node_id, initializer_list<json_node_t> node_children = initializer_list<json_node_t>());
    json_node_t& add(const json_node_t& node);
    json_node_t& add(const initializer_list<json_node_t>& nodes);
};

json_node_t::json_node_t(int node_id, initializer_list<json_node_t> node_children) : id(node_id), child(node_children) {
}

json_node_t& json_node_t::add(const json_node_t& node) {
    child.push_back(node);
    return child.back();
}

json_node_t& json_node_t::add(const initializer_list<json_node_t>& nodes) {
    child.insert(child.end(), nodes);
    return child.back();
}

int main() {
    json_node_t node_a = {1, {{2, {}}, {3, {{5, {}}, {6, {}}}}, {4, {}}}};

    json_node_t node_b = {1, {2, {3, {5, 6}}, 4}};

    json_node_t node_c(1);
    node_c.add(2);
    node_c.add(3).add({5, 6});
    node_c.add(4);

    cout << json(node_a).dump(2) << endl << endl;
    cout << json(node_b).dump(2) << endl << endl;
    cout << json(node_c).dump(2) << endl;
    return 0;
}
Sign up to request clarification or add additional context in comments.

2 Comments

thanks. Looks OK to use the to_json method. However I find it difficult to create nodes. This initialization works OK {1, {{2, {}}, {3, {{5, {}}, {6, {}}}}, {4, {}}}}; but is there any easier way to add nodes, ie add children at the parent?
@cateof Since json_node_t is your class, you can add any convenience methods suitable for the intended usage. I added a couple of examples into the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.