You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE处理含std::optional成员的结构体序列化问题

解决nlohmann::json中含std::optional成员结构体的反序列化键缺失问题

问题根源在于NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE宏默认使用at()方法访问JSON键,当键不存在时会直接抛出异常,无法自动给std::optional成员赋值std::nullopt。要实现需求,最直接的方式是手动实现结构体的序列化/反序列化函数,替代宏定义的自动生成逻辑,具体操作如下:

1. 定义目标结构体

假设我们有如下包含std::optional成员的结构体:

#include <nlohmann/json.hpp>
#include <optional>
#include <string>

using json = nlohmann::json;

struct MyStruct {
    int id; // 必选字段
    std::optional<std::string> name; // 可选字段
    std::optional<int> value; // 可选字段
};

2. 手动实现from_json和to_json函数

  • 反序列化(from_json):对必选字段用at()确保存在(缺失时抛异常),对可选字段通过find()或contains()判断键是否存在,不存在则赋值std::nullopt:
void from_json(const json& j, MyStruct& s) {
    // 必选字段强制校验,缺失则抛出异常
    j.at("id").get_to(s.id);

    // 处理可选字段name:键存在则反序列化,否则设为nullopt
    auto name_it = j.find("name");
    if (name_it != j.end()) {
        name_it->get_to(s.name);
    } else {
        s.name = std::nullopt;
    }

    // 处理可选字段value:更简洁的写法
    s.value = j.contains("value") ? j["value"].get<std::optional<int>>() : std::nullopt;
}
  • 序列化(to_json):仅序列化std::optional中有值的成员,避免JSON中出现多余的null键:
void to_json(json& j, const MyStruct& s) {
    j["id"] = s.id;
    if (s.name) {
        j["name"] = *s.name;
    }
    if (s.value) {
        j["value"] = *s.value;
    }
}

3. 验证效果

当反序列化缺少可选字段的JSON时,对应std::optional成员会自动被设为std::nullopt,不会抛出异常。例如:

// 缺少name字段的JSON
json j = R"({"id": 123, "value": 456})"_json;
MyStruct s = j.get<MyStruct>();
// s.name == std::nullopt,s.value == 456,s.id == 123

由于你已经实现了std::optional的adl_serializer,上述代码中的get_to()和get<std::optional<T>>()会正常处理JSON null与std::nullopt的转换。

内容的提问来源于stack exchange,提问作者SupAl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 17:22:41