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

to_json / from_json with nested type #1648

Closed
btut opened this issue Jun 21, 2019 · 17 comments
Closed

to_json / from_json with nested type #1648

btut opened this issue Jun 21, 2019 · 17 comments
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@btut
Copy link

btut commented Jun 21, 2019

Hi,

  • Describe what you want to achieve.

I have a struct that contains a vector of different structs and am unable to parse it using this library.
The readme lists an example for to_json and from_json function definitions, is such an example available in doc/examples? I would love to see some MWE I could adapt for this.

  • Describe what you tried.

I tried to define to_json and from_json (I actually only need from_json so to_json is left blank) as in the readme, but could not get it to work:

`
#ifndef CONFIGURATION_H
#define CONFIGURATION_H

#include "json.hpp"
#include

using nlohmann::json;

struct SignalConfiguration {
std::string Name;
};

struct AppConfiguration {
uint32_t Length;
std::vector SignalConfigurations;
};

void to_json(json& J, const AppConfiguration& AC) {
//This direction is not needed
(void)J;
(void)AC;
}

void to_json(json& J, const SignalConfiguration& SC) {
//This direction is not needed
(void)J;
(void)SC;
}

void from_json(json& J, const AppConfiguration& AC) {
J.at("Length").get_to(AC.Length);
J.at("SignalConfigurations").get_to(AC.SignalConfigurations);
}

void from_json(json& J, const SignalConfiguration& SC) {
J.at("Name").get_to(SC.Name);
}

AppConfiguration AppConfig;

bool readConfigFile(std::string ConfigPath) {

std::ifstream ConfigFile;
ConfigFile.open(ConfigPath);

if (!ConfigFile) {
return false;
}

json ConfigObj;
ConfigFile >> ConfigObj;
AppConfig = ConfigFile;

return true;
}

#endif // CONFIGURATION_H
`

This yields a lot of errors:
In file included from main.cpp:1: ./configuration.h:32:34: error: no matching member function for call to 'get_to' J.at("SignalConfigurations").get_to(AC.SignalConfigurations); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ ./json.hpp:15481:17: note: candidate template ignored: requirement 'detail::has_from_json<basic_json_t, const vector<SignalConfiguration, allocator<SignalConfiguration> > >::value' was not satisfied [with ValueType = const std::vector<SignalConfiguration, std::allocator<SignalConfiguration> >] ValueType & get_to(ValueType& v) const noexcept(noexcept( ^ ./json.hpp:15493:11: note: candidate template ignored: could not match 'T [N]' against 'const std::vector<SignalConfiguration>' Array get_to(T (&v)[N]) const ^ In file included from main.cpp:1: ./configuration.h:52:13: error: no viable overloaded '=' AppConfig = ConfigFile; ./configuration.h:13:8: note: candidate function (the implicit move assignment operator) not viable: no known conversion from 'std::ifstream' (aka 'basic_ifstream<char>') to 'AppConfiguration' for 1st argument struct AppConfiguration { ^ ./configuration.h:13:8: note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'std::ifstream' (aka 'basic_ifstream<char>') to 'const AppConfiguration' for 1st argument struct AppConfiguration { ^ In file included from main.cpp:1: In file included from ./configuration.h:4: ./json.hpp:1576:17: error: cannot assign to variable 'val' with const-qualified type 'const unsigned int &' val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); ~~~ ^ ./json.hpp:1665:16: note: in instantiation of function template specialization 'nlohmann::detail::from_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, adl_serializer>, const unsigned int, 0>' requested here return from_json(j, val); ^ ./json.hpp:2222:9: note: in instantiation of function template specialization 'nlohmann::detail::from_json_fn::operator()<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, adl_serializer>, const unsigned int>' requested here ::nlohmann::from_json(std::forward<BasicJsonType>(j), val); ^ ./json.hpp:15484:36: note: in instantiation of function template specialization 'nlohmann::adl_serializer<const unsigned int, void>::from_json<const nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, adl_serializer> &, const unsigned int>' requested here JSONSerializer<ValueType>::from_json(*this, v); ^ ./configuration.h:31:20: note: in instantiation of function template specialization 'nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, adl_serializer>::get_to<const unsigned int, 0>' requested here J.at("Length").get_to(AC.Length); ^ ./json.hpp:1570:56: note: variable 'val' declared const here void from_json(const BasicJsonType& j, ArithmeticType& val) ~~~~~~~~~~~~~~~~^~~ ./json.hpp:1581:17: error: cannot assign to variable 'val' with const-qualified type 'const unsigned int &' val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); ~~~ ^ ./json.hpp:1570:56: note: variable 'val' declared const here void from_json(const BasicJsonType& j, ArithmeticType& val) ~~~~~~~~~~~~~~~~^~~ ./json.hpp:1586:17: error: cannot assign to variable 'val' with const-qualified type 'const unsigned int &' val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); ~~~ ^ ./json.hpp:1570:56: note: variable 'val' declared const here void from_json(const BasicJsonType& j, ArithmeticType& val) ~~~~~~~~~~~~~~~~^~~ ./json.hpp:1591:17: error: cannot assign to variable 'val' with const-qualified type 'const unsigned int &' val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>()); ~~~ ^ ./json.hpp:1570:56: note: variable 'val' declared const here void from_json(const BasicJsonType& j, ArithmeticType& val) ~~~~~~~~~~~~~~~~^~~ ./json.hpp:1388:7: error: no viable overloaded '=' s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); ~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ./json.hpp:1665:16: note: in instantiation of function template specialization 'nlohmann::detail::from_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, adl_serializer>, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, 0>' requested here return from_json(j, val); ^ ./json.hpp:2222:9: note: in instantiation of function template specialization 'nlohmann::detail::from_json_fn::operator()<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, adl_serializer>, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >' requested here ::nlohmann::from_json(std::forward<BasicJsonType>(j), val); ^ ./json.hpp:15484:36: note: in instantiation of function template specialization 'nlohmann::adl_serializer<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, void>::from_json<const nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, adl_serializer> &, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >' requested here JSONSerializer<ValueType>::from_json(*this, v); ^ ./configuration.h:36:18: note: in instantiation of function template specialization 'nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, adl_serializer>::get_to<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, 0>' requested here J.at("Name").get_to(SC.Name); ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/basic_string.h:664:7: note: candidate function not viable: 'this' argument has type 'const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >', but method is not marked const operator=(const basic_string& __str) ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/basic_string.h:809:8: note: candidate function not viable: 'this' argument has type 'const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >', but method is not marked const operator=(const _Tp& __svt) ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/basic_string.h:703:7: note: candidate function not viable: 'this' argument has type 'const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >', but method is not marked const operator=(const _CharT* __s) ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/basic_string.h:714:7: note: candidate function not viable: 'this' argument has type 'const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >', but method is not marked const operator=(_CharT __c) ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/basic_string.h:732:7: note: candidate function not viable: 'this' argument has type 'const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >', but method is not marked const operator=(basic_string&& __str) ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/basic_string.h:795:7: note: candidate function not viable: 'this' argument has type 'const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >', but method is not marked const operator=(initializer_list<_CharT> __l) ^ 7 errors generated.

  • Describe which system (OS, compiler) you are using.

I am using clang-6.0 on ubuntu 19.04 with C++17.

clang++-6.0 main.cpp -std=c++17

  • Describe which version of the library you are using (release version, develop branch).

I am using the most recent single-header include (aa4c45e).

@btut btut changed the title Hi, to_json / from_json with nested type Jun 21, 2019
@nlohmann nlohmann added the state: needs more info the author of the issue needs to provide more details label Jun 21, 2019
@btut
Copy link
Author

btut commented Jun 21, 2019

Sorry, hit return while typing, I now updated the question. Let me check if I can build the unit test with my build environment.

@btut
Copy link
Author

btut commented Jun 21, 2019

All tests are passing!

@btut
Copy link
Author

btut commented Jun 21, 2019

I tested the release version as well, same behavior.

@nickaein
Copy link
Contributor

The main issue was that you had to swap the constness of the parameters between to_json and from_json. In from_json function, the input json object must be const. Here is the fixed version that compiles (plus some minor fixes):

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

using nlohmann::json;


struct SignalConfiguration 
{
    std::string Name;
};

struct AppConfiguration 
{
    uint32_t Length;
    std::vector<SignalConfiguration> SignalConfigurations;
};

void from_json(const json& J, SignalConfiguration& SC) 
{
    J.at("Name").get_to(SC.Name);
}

void from_json(const json& J, AppConfiguration& AC) 
{
    J.at("Length").get_to(AC.Length);
    J.at("SignalConfigurations").get_to(AC.SignalConfigurations);
}


AppConfiguration AppConfig;

bool readConfigFile(std::string ConfigPath) 
{
    std::ifstream ConfigFile;
    ConfigFile.open(ConfigPath);

    if (!ConfigFile) {
        return false;
    }

    json ConfigObj;
    ConfigFile >> ConfigObj;
    AppConfig = ConfigObj.get<AppConfiguration>();

    return true;
}

int main()
{
    readConfigFile("config.json");
}

@nlohmann
Copy link
Owner

@btut Does #1648 (comment) fix the issue?

@nlohmann nlohmann added solution: proposed fix a fix for the issue has been proposed and waits for confirmation and removed state: needs more info the author of the issue needs to provide more details labels Jun 24, 2019
@btut
Copy link
Author

btut commented Jun 24, 2019

The main issue was that you had to swap the constness of the parameters between to_json and from_json. In from_json function, the input json object must be const.
That makes a lot of sense.
Here is the fixed version that compiles (plus some minor fixes)
Thank you so much! It seems obvious that the from_json function of the nested struct needs to go first so the second one can find it. Still, I would have not found that mistake by myself.

@wyfSunflower
Copy link

The main issue was that you had to swap the constness of the parameters between to_json and from_json. In from_json function, the input json object must be const. Here is the fixed version that compiles (plus some minor fixes):

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

using nlohmann::json;


struct SignalConfiguration 
{
    std::string Name;
};

struct AppConfiguration 
{
    uint32_t Length;
    std::vector<SignalConfiguration> SignalConfigurations;
};

void from_json(const json& J, SignalConfiguration& SC) 
{
    J.at("Name").get_to(SC.Name);
}

void from_json(const json& J, AppConfiguration& AC) 
{
    J.at("Length").get_to(AC.Length);
    J.at("SignalConfigurations").get_to(AC.SignalConfigurations);
}


AppConfiguration AppConfig;

bool readConfigFile(std::string ConfigPath) 
{
    std::ifstream ConfigFile;
    ConfigFile.open(ConfigPath);

    if (!ConfigFile) {
        return false;
    }

    json ConfigObj;
    ConfigFile >> ConfigObj;
    AppConfig = ConfigObj.get<AppConfiguration>();

    return true;
}

int main()
{
    readConfigFile("config.json");
}

I have add const,but still compile error
`#ifndef MAP_H
#define MAP_H
#include <nlohmann/json.hpp>
#include
using json=nlohmann::json;
namespace tusk {
struct CurvePoint{
CurvePoint(int idx, int x, int y){
this->x=x;
this->y=y;
this->idx=idx;
}
int idx;
int x;
int y;
};
void to_json(json& j,const CurvePoint& cp){
j = json{{"idx",cp.idx},{"x",cp.x},{"y",cp.y}};
}
void from_json(const json& j, CurvePoint& cp){
j.at("idx").get_to(cp.idx);
j.at("x").get_to(cp.x);
j.at("y").get_to(cp.y);
}
struct MapNodeOutEdge{
MapNodeOutEdge(int nid,int maxV,int laserD,int laserLD,int laserRD,int obsRunType,
int runMode,vector curvePoints){
this->nid=nid;
this->maxV=maxV;
this->laserD=laserD;
this->laserLD=laserLD;
this->laserRD=laserRD;
this->obsRunType=obsRunType;
this->runMode=runMode;
this->curvePoints=curvePoints;
}
int nid;
int maxV;
int laserD;
int laserLD;
int laserRD;
int obsRunType;
int runMode;
vector curvePoints;
};
void to_json(json& j, const MapNodeOutEdge& mnoe){
j = json{{"nid",mnoe.nid},{"maxV",mnoe.maxV},{"laserD",mnoe.laserD},{"laserLD",mnoe.laserLD},
{"laserRD",mnoe.laserRD},{"obsRunType",mnoe.obsRunType},{"runMode",mnoe.runMode},
{"curvePoints",mnoe.curvePoints}};
}
void from_json(const json& j,MapNodeOutEdge& mnoe){
j.at("nid").get_to(mnoe.nid);
j.at("maxV").get_to(mnoe.maxV);
j.at("laserD").get_to(mnoe.laserD);
j.at("laserLD").get_to(mnoe.laserLD);
j.at("laserRD").get_to(mnoe.laserRD);
j.at("obsRunType").get_to(mnoe.obsRunType);
j.at("runMode").get_to(mnoe.runMode);
j.at("curvePoints").get_to(mnoe.curvePoints);
}
struct Node{
Node(){

}
Node(int id,vector<MapNodeOutEdge> outEdges,int x,int y,int z,int type,
     int layerId,int rotateD,int maxW,int slamOnlineFlag){
  this->id=id;
  this->outEdges=outEdges;
  this->x=x;
  this->y=y;
  this->z=z;
  this->type=type;
  this->layerId=layerId;
  this->rotateD=rotateD;
  this->maxW=maxW;
  this->slamOnlineFlag=slamOnlineFlag;
}
int id;
vector<MapNodeOutEdge>  outEdges;
int x;
int y;
int z;
int type;
int layerId;
int rotateD;
int maxW;
int slamOnlineFlag;

};
void to_json(json& j,const Node& n){
j = {{"id",n.id},{"x",n.x},{"y",n.y},{"z",n.z},{"type",n.type},{"layerId",n.layerId},
{"rotateD",n.rotateD},{"maxW",n.maxW},{"slamOnlineFlag",n.slamOnlineFlag}};
}
void from_json(const json& j,Node& n){
j.at("id").get_to(n.id);
j.at("outEdges").get_to(n.outEdges);
j.at("x").get_to(n.x);
j.at("y").get_to(n.y);
j.at("z").get_to(n.z);
j.at("type").get_to(n.type);
j.at("layerId").get_to(n.layerId);
j.at("rotateD").get_to(n.rotateD);
j.at("maxW").get_to(n.maxW);
j.at("slamOnlineFlag").get_to(n.slamOnlineFlag);
}
}

#endif // MAP_H
`

@gregmarr
Copy link
Contributor

The functions need to be inside the namespace containing the type.

@falbrechtskirchinger
Copy link
Contributor

falbrechtskirchinger commented Jun 29, 2022

The functions need to be inside the namespace containing the type.

They are, I believe.

CurvePoint and MapNodeOutEdge aren't default constructible. Either add default constructors or have a look at: https://json.nlohmann.me/features/arbitrary_types/#how-can-i-use-get-for-non-default-constructiblenon-copyable-types

@gregmarr
Copy link
Contributor

gregmarr commented Jun 29, 2022

Ah, I missed an opening brace from the constructor. Reading code in unindented proportional fonts is hard. :)

namespace tusk {
    struct CurvePoint {
        CurvePoint(int idx, int x, int y) {
            this->x=x;
            this->y=y;
            this->idx=idx;
        }
        int idx;
        int x;
        int y;
    };
    void to_json(json& j,const CurvePoint& cp) {
        j = json{{"idx",cp.idx},{"x",cp.x},{"y",cp.y}};
    }

@falbrechtskirchinger
Copy link
Contributor

Yeah, I cheated by formatting it in an editor. :-P

@gregmarr
Copy link
Contributor

I really wish GH had a "start of code block" markup instead of requiring 4 spaces at the start of each line.

@falbrechtskirchinger
Copy link
Contributor

It does. 3 backticks on a single line to start and end a block. I never use leading spaces. And you can optionally specify the language for syntax highlighting:

```

struct foo {};

```cpp

struct foo {};

```json

{
    "foo": 42
}

@gregmarr
Copy link
Contributor

gregmarr commented Jun 29, 2022

Hmm, I thought I had tried that before. I use that all the time on Slack.

Thanks for the reminder.

@wyfSunflower
Copy link

Thanks! it compile ok,but convert error when field in json is null
`#ifndef MAP_H
#define MAP_H
#include <nlohmann/json.hpp>
#include
using json=nlohmann::json;
namespace tusk {
struct CurvePoint{
CurvePoint(){

}
CurvePoint(int idx, int x, int y){
  this->x=x;
  this->y=y;
  this->idx=idx;
}
int idx;
int x;
int y;

};
void to_json(json& j,const CurvePoint& cp){
j = json{{"idx",cp.idx},{"x",cp.x},{"y",cp.y}};
}
void from_json(const json& j, CurvePoint& cp){
j.at("idx").get_to(cp.idx);
j.at("x").get_to(cp.x);
j.at("y").get_to(cp.y);
}
struct MapNodeOutEdge{
MapNodeOutEdge(){

}
MapNodeOutEdge(int nid,int maxV,int laserD,int laserLD,int laserRD,int obsRunType,
               int runMode,vector<CurvePoint> curvePoints){
  this->nid=nid;
  this->maxV=maxV;
  this->laserD=laserD;
  this->laserLD=laserLD;
  this->laserRD=laserRD;
  this->obsRunType=obsRunType;
  this->runMode=runMode;
  this->curvePoints=curvePoints;
}
int nid;
int maxV;
int laserD;
int laserLD;
int laserRD;
int obsRunType;
int runMode;
vector<CurvePoint> curvePoints;

};
void to_json(json& j, const MapNodeOutEdge& mnoe){
j = json{{"nid",mnoe.nid},{"maxV",mnoe.maxV},{"laserD",mnoe.laserD},{"laserLD",mnoe.laserLD},
{"laserRD",mnoe.laserRD},{"obsRunType",mnoe.obsRunType},{"runMode",mnoe.runMode},
{"curvePoints",mnoe.curvePoints}};
}
void from_json(const json& j,MapNodeOutEdge& mnoe){
j.at("nid").get_to(mnoe.nid);
j.at("maxV").get_to(mnoe.maxV);
j.at("laserD").get_to(mnoe.laserD);
j.at("laserLD").get_to(mnoe.laserLD);
j.at("laserRD").get_to(mnoe.laserRD);
j.at("obsRunType").get_to(mnoe.obsRunType);
j.at("runMode").get_to(mnoe.runMode);
j.at("curvePoints").get_to(mnoe.curvePoints);
}
struct Node{
Node(){

}
Node(int id,vector<MapNodeOutEdge> outEdges,int x,int y,int z,int type,
     int layerId,int rotateD,int maxW,int slamOnlineFlag){
  this->id=id;
  this->outEdges=outEdges;
  this->x=x;
  this->y=y;
  this->z=z;
  this->type=type;
  this->layerId=layerId;
  this->rotateD=rotateD;
  this->maxW=maxW;
  this->slamOnlineFlag=slamOnlineFlag;
}
int id;
vector<MapNodeOutEdge>  outEdges;
int x;
int y;
int z;
int type;
int layerId;
int rotateD;
int maxW;
int slamOnlineFlag;

};
void to_json(json& j,const Node& n){
j = {{"id",n.id},{"x",n.x},{"y",n.y},{"z",n.z},{"type",n.type},{"layerId",n.layerId},
{"rotateD",n.rotateD},{"maxW",n.maxW},{"slamOnlineFlag",n.slamOnlineFlag}};
}
void from_json(const json& j,Node& n){
j.at("id").get_to(n.id);
j.at("outEdges").get_to(n.outEdges);
j.at("x").get_to(n.x);
j.at("y").get_to(n.y);
j.at("z").get_to(n.z);
j.at("type").get_to(n.type);
j.at("layerId").get_to(n.layerId);
j.at("rotateD").get_to(n.rotateD);
j.at("maxW").get_to(n.maxW);
j.at("slamOnlineFlag").get_to(n.slamOnlineFlag);
}
struct Nodes{
Nodes(){

}
Nodes(vector<Node> nodes){
  this->nodes=nodes;
}
vector<Node> nodes;

};
void to_json(json& j, const Nodes& n){
j = {{"nodes",n.nodes}};
}
void from_json(const json& j, Nodes& n){
j.at("nodes").get_to(n.nodes);
}

}
#endif // MAP_H`

`void parseMap(string f){

std::ifstream i(f);
json mj;
i >> mj;
auto n = mj.get<tusk::Nodes>();
cout<<"n.nodes[0].id:"<<n.nodes[0].id<<endl;

}`

{
"nodes":[
{
"id":1,
"layerId":1,
"outEdges":[
{
"nid":2,
"maxV":500,
"laserD":600,
"laserLD":200,
"obsRunType":1,
"runMode":2
}
],
"type":1,
"x":0,
"y":0,
"z":1,
"rotateD":500,
"maxW":300,
"slamOnlineFlag":1
},
{
"id":2,
"layerId":1,
"outEdges":[
{
"nid":3
}
],
"type":1,
"x":2,
"y":0,
"z":1
},
{
"id":3,
"layerId":1,
"outEdges":[
{
"nid":4,
"maxV":800,
"curvePoints":[
{
"idx":1,
"x":4,
"y":0
},
{
"idx":2,
"x":6,
"y":2
}
]
}
],
"type":1,
"x":4,
"y":0,
"z":1
},
{
"id":4,
"layerId":1,
"outEdges":[
{
"nid":5
}
],
"type":1,
"x":6,
"y":4,
"z":1
},
{
"id":5,
"layerId":1,
"outEdges":[
{
"nid":4
}
],
"type":1,
"x":6,
"y":6,
"z":1
}
]
}

@wyfSunflower
Copy link

wyfSunflower commented Jun 29, 2022

the above code throw error when run:
terminate called after throwing an instance of 'nlohmann::detail::out_of_range'
what(): [json.exception.out_of_range.403] key 'laserRD' not found

How can set default value ,such as 0 or null when key is not exist in json . in this json key laserRD is not exist,I want set Node.laserRD=0

@falbrechtskirchinger
Copy link
Contributor

at() throws an exception for non-existent keys.
https://json.nlohmann.me/api/basic_json/at/

You'll have to check if the key exists first. See:
https://json.nlohmann.me/api/basic_json/contains/

if(j.contains("key")) j.at("key").get_to(key);

(Remember to either default initialize your fields or add an else branch to set your fields to something meaningful.)

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

6 participants