Json: Deserializing to vector

Created on 29 Dec 2018  路  2Comments  路  Source: nlohmann/json

Can't quite figure out why I'm getting this error:

terminate called after throwing an instance of 'nlohmann::detail::out_of_range'
  what():  [json.exception.out_of_range.403] key 'required' not found

Here's my code:

#include <nlohmann/json.hpp>
#include <string>
#include <iostream>
#include <fstream>

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

namespace ns {

    struct course {
        int number{};
        string subject;
        int credits{};
        vector<course> required;
    };

    void to_json(json &j, const course &c) {
        json required_json;
        json orr_json;
        json poc_json;
        json co_json;
        for (const auto &child : c.required)
        {
            json i;
            to_json(i, child);
            required_json.push_back(i);
        }
        j = json{{"number",  c.number},
                 {"subject", c.subject},
                 {"credits", c.credits},
                 {"required", required_json}};
    }

    void from_json(const json &j, course &c) {
        j.at("number").get_to(c.number);
        j.at("subject").get_to(c.subject);
        j.at("credits").get_to(c.credits);
        j.at("required").get_to<std::vector<course>>(c.required);
    }
}

vector<ns::course> grabber(ifstream &x);

int main() {
    ifstream x("curriculum.json");
    grabber(x);
    return 0;
}

vector<ns::course> grabber(ifstream &x) {
    json j;
    x >> j;
    ns::course c;
    vector<ns::course> v;

    ns::from_json(j,c);

    return v;
}

Here's my .json file: https://hastebin.com/wizofetomu.json

I'd appreciate any help, I've continually reviewed the documentation but can't figure out what I'm doing incorrectly.

question proposed fix

Most helpful comment

The exception is from line

j.at("required").get_to<std::vector<course>>(c.required);

Is is thrown, because from_json is called more than once:

  • First for the whole JSON document. There, a key "required" exists.
  • Then, recursively, in the translation of each course in the vector. However, elements like {"number": 104,"subject": "MATH","credits": 3} do not have a key "required", so at throws.

You should adjust your code to reflect that not every course needs to have a "required" key, e.g. like

        if (j.find("required") != j.end())
            j.at("required").get_to<std::vector<course>>(c.required);

As a side note, you do not need to call to_json explicitly. Code like

required_json.push_back(child);

works as well.

All 2 comments

The exception is from line

j.at("required").get_to<std::vector<course>>(c.required);

Is is thrown, because from_json is called more than once:

  • First for the whole JSON document. There, a key "required" exists.
  • Then, recursively, in the translation of each course in the vector. However, elements like {"number": 104,"subject": "MATH","credits": 3} do not have a key "required", so at throws.

You should adjust your code to reflect that not every course needs to have a "required" key, e.g. like

        if (j.find("required") != j.end())
            j.at("required").get_to<std::vector<course>>(c.required);

As a side note, you do not need to call to_json explicitly. Code like

required_json.push_back(child);

works as well.

Thank you for the assistance!

Was this page helpful?
0 / 5 - 0 ratings