Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserializing to vector #1407

Closed
pshadoyan opened this issue Dec 29, 2018 · 2 comments
Closed

Deserializing to vector #1407

pshadoyan opened this issue Dec 29, 2018 · 2 comments
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@pshadoyan
Copy link

pshadoyan commented Dec 29, 2018

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.

@nlohmann
Copy link
Owner

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.

@nlohmann nlohmann added kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation labels Dec 29, 2018
@pshadoyan
Copy link
Author

Thank you for the assistance!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

2 participants