nlohmann json调用emplace_back()触发type_error.311异常原因咨询
nlohmann json调用emplace_back抛出type_error 311问题
报错现象
使用nlohmann json库编写代码时,遇到如下运行时报错:
terminate called after throwing an instance of 'nlohmann::detail::type_error' what(): [json.exception.type_error.311] cannot use emplace_back() with object Aborted (core dumped)
查阅参考文档时发现,文档记录的311号错误描述与实际遇到的提示不符,文档标注内容为:
json.exception.type_error.311 cannot use emplace_back() with string The emplace_back() member function can only be executed for certain JSON types.
复现代码
初始实现代码如下,运行到标注位置时触发上述错误:
#include "common/nlohmann/json.hpp" using json = nlohmann::json; using ordered_json = nlohmann::ordered_json; void AClass::do_something(){ std::ofstream o_file(output_file); ordered_json json_result; ordered_json json_; json_result["output"]=json::array(); // 获取结构体result的内容 json_=getJsonFromResult(result); json_result.emplace_back(json_); //<-- 报错触发位置 o_file<<json_result.dump(); o_file.close(); } ordered_json AClass::getJsonFromResult(TheResult& result){ ordered_json json_; json_["blabla"]="blabla"; return json_; }
如果调整代码,将emplace_back()的调用移到getJsonFromResult()函数内部执行,则不会触发任何异常,修改后的代码如下:
void AClass::do_something(){ std::ofstream o_file(output_file); ordered_json json_result; ordered_json json_; json_result["output"]=json::array(); // 获取结构体result的内容 json_=getJsonFromResult(result); // 移除此处的emplace_back调用 o_file<<json_result.dump(); o_file.close(); } ordered_json AClass::getJsonFromResult(TheResult& result){ ordered_json json_; json_["blabla"]="blabla"; json_result["output"].emplace_back(json_); // 此处调用可正常运行(原代码此处缺右括号为输入笔误) return json_; }
补充说明:json_result是AClass的成员变量。
待确认疑问:
- 为什么
emplace_back()在getJsonFromResult()函数内部调用可以正常运行,在do_something()中调用就会触发异常? - 该现象是否和传入参数为函数返回值有关?
问题根因
这个现象和函数返回值没有任何关系,是两个代码写法错误叠加导致的:
- 局部变量遮蔽同名成员变量
do_something()函数内部声明了一个和类成员变量完全同名的局部变量ordered_json json_result;,该函数内所有对json_result的操作,针对的都是这个刚创建的局部对象,而非类成员变量。
这个局部json_result默认是JSON object类型(声明后通过[]运算符添加了"output"键,类型不会变化),而emplace_back()是JSON数组类型的专属操作方法,仅支持向数组尾部追加元素,直接对object类型调用该方法必然抛出类型错误。 - 调用方法的目标对象错误
代码中明确写了json_result["output"]=json::array();,说明本意是向output键对应的数组内追加元素,但实际写的是json_result.emplace_back(json_),操作目标是外层的object对象,并非内层的output数组。
移到getJsonFromResult()内可以正常运行的原因非常简单:该函数内部没有定义同名的局部json_result变量,访问的是类的成员变量,且操作目标是json_result["output"]这个数组,对数组调用emplace_back()属于合法操作,自然不会报错。
至于文档和实际报错提示不一致的问题,是因为查阅的是旧版本库的文档,本地实际使用的nlohmann json版本更高,311错误的提示覆盖了所有不支持emplace_back()的类型(包括object、string、数值等),并非只有旧文档标注的string场景。
修复方案
只需要修正do_something()中的两个问题即可:删除多余的局部变量声明避免遮蔽成员变量,同时将emplace_back()的调用目标改为output对应的数组:
void AClass::do_something(){ std::ofstream o_file(output_file); ordered_json json_; json_result["output"]=json::array(); json_=getJsonFromResult(result); json_result["output"].emplace_back(json_); o_file<<json_result.dump(); o_file.close(); }
内容的提问来源于stack exchange,提问作者KansaiRobot
相关产品推荐
相关产品推荐

