使用 nlohmann json 包从 json 转换时出错
Error in converting from json using nlohmann json package
我正在尝试转换 json 形式的
{
"content": {
"test_key": "test"
},
"sender": "alice",
"type": "key_type"
}
我的对象是
template<class Content>
struct Event
{
Content content;
std::string type;
};
正在使用模板,因为内容的结构不固定。当我尝试使用类似于
的 from_json 时
template<class Content>
void
from_json(const nlohmann::json &obj, Event<Content> &event)
{
event.content = obj.at("content").get<Content>();
event.type = obj.at("type").get<std::string>();
}
我遇到错误
[json.exception.out_of_range.403] key 'content' not found
尽管 json 中有内容键。为什么会这样?
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
using namespace std;
template<typename Content>
struct Event
{
Content content;
string type;
};
template<typename Content>
void from_json(const nlohmann::json &obj, Event<Content> &event)
{
event.content = obj.at("content").get<Content>();
event.type = obj.at("type").get<string>();
}
struct Key{
string test_key;
string random_data;
};
int main(){
json j={{"content",{{"test_key","test"}}},{"sender","alice"},{"type","key_type"}};
Event<Key> event_instance;
try{
from_json(j,event_instance);
}
catch(json::exception& e){
cout<<e.what()<<endl;
}
}
以上代码是一个最小的可重现示例
缺少的是对您的类型的序列化程序支持 Key
。添加后,提取工作:
void from_json(const nlohmann::json& obj, Key& k) {
k.test_key = obj.at("test_key").get<std::string>();
// k.random_data missing in json
}
template<typename Content>
void from_json(const nlohmann::json& obj, Event<Content>& event) {
event.content = obj.at("content").get<Content>();
event.type = obj.at("type").get<std::string>();
}
要处理 Key
中的 random_data
等可选字段,您可以创建一个辅助函数,此处称为 get_optional
,其中 returns 一个 C++17 std::optional<T>
。对于早期的 C++ 版本,您可以使用 boost::optional
.
#include <nlohmann/json.hpp>
#include <iostream>
#include <optional>
#include <string>
using json = nlohmann::json;
template<typename Content>
struct Event {
Content content{};
std::string type{};
};
struct Key {
std::string test_key{};
std::optional<std::string> random_data{}; // optional field made optional
};
template<typename T>
std::optional<T> get_optional(const json& obj, const std::string& key) try {
return obj.at(key).get<T>();
} catch(const json::exception&) {
return std::nullopt;
}
void from_json(const json& obj, Key& k) {
k.test_key = obj.at("test_key").get<std::string>();
k.random_data = get_optional<std::string>(obj, "random_data");
}
template<typename Content>
void from_json(const json& obj, Event<Content>& event) {
event.content = obj.at("content").get<Content>();
event.type = obj.at("type").get<std::string>();
}
int main() {
json j = {{"content", {{"test_key", "test"}}},
{"sender", "alice"},
{"type", "key_type"}};
try {
auto event_instance = j.get<Event<Key>>();
std::cout << event_instance.content.test_key << '\n';
if(event_instance.content.random_data) {
std::cout << event_instance.content.random_data.value() << '\n';
} else {
std::cout << "no random_data\n";
}
std::cout << event_instance.type << '\n';
} catch(const json::exception& e) {
std::cerr << e.what() << std::endl;
}
}
我正在尝试转换 json 形式的
{
"content": {
"test_key": "test"
},
"sender": "alice",
"type": "key_type"
}
我的对象是
template<class Content>
struct Event
{
Content content;
std::string type;
};
正在使用模板,因为内容的结构不固定。当我尝试使用类似于
的 from_json 时template<class Content>
void
from_json(const nlohmann::json &obj, Event<Content> &event)
{
event.content = obj.at("content").get<Content>();
event.type = obj.at("type").get<std::string>();
}
我遇到错误
[json.exception.out_of_range.403] key 'content' not found
尽管 json 中有内容键。为什么会这样?
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
using namespace std;
template<typename Content>
struct Event
{
Content content;
string type;
};
template<typename Content>
void from_json(const nlohmann::json &obj, Event<Content> &event)
{
event.content = obj.at("content").get<Content>();
event.type = obj.at("type").get<string>();
}
struct Key{
string test_key;
string random_data;
};
int main(){
json j={{"content",{{"test_key","test"}}},{"sender","alice"},{"type","key_type"}};
Event<Key> event_instance;
try{
from_json(j,event_instance);
}
catch(json::exception& e){
cout<<e.what()<<endl;
}
}
以上代码是一个最小的可重现示例
缺少的是对您的类型的序列化程序支持 Key
。添加后,提取工作:
void from_json(const nlohmann::json& obj, Key& k) {
k.test_key = obj.at("test_key").get<std::string>();
// k.random_data missing in json
}
template<typename Content>
void from_json(const nlohmann::json& obj, Event<Content>& event) {
event.content = obj.at("content").get<Content>();
event.type = obj.at("type").get<std::string>();
}
要处理 Key
中的 random_data
等可选字段,您可以创建一个辅助函数,此处称为 get_optional
,其中 returns 一个 C++17 std::optional<T>
。对于早期的 C++ 版本,您可以使用 boost::optional
.
#include <nlohmann/json.hpp>
#include <iostream>
#include <optional>
#include <string>
using json = nlohmann::json;
template<typename Content>
struct Event {
Content content{};
std::string type{};
};
struct Key {
std::string test_key{};
std::optional<std::string> random_data{}; // optional field made optional
};
template<typename T>
std::optional<T> get_optional(const json& obj, const std::string& key) try {
return obj.at(key).get<T>();
} catch(const json::exception&) {
return std::nullopt;
}
void from_json(const json& obj, Key& k) {
k.test_key = obj.at("test_key").get<std::string>();
k.random_data = get_optional<std::string>(obj, "random_data");
}
template<typename Content>
void from_json(const json& obj, Event<Content>& event) {
event.content = obj.at("content").get<Content>();
event.type = obj.at("type").get<std::string>();
}
int main() {
json j = {{"content", {{"test_key", "test"}}},
{"sender", "alice"},
{"type", "key_type"}};
try {
auto event_instance = j.get<Event<Key>>();
std::cout << event_instance.content.test_key << '\n';
if(event_instance.content.random_data) {
std::cout << event_instance.content.random_data.value() << '\n';
} else {
std::cout << "no random_data\n";
}
std::cout << event_instance.type << '\n';
} catch(const json::exception& e) {
std::cerr << e.what() << std::endl;
}
}