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

使用nlohmann JSON解析还原类实例的报错问题咨询

C++使用nlohmann/json解析JSON还原类实例的编译错误解决

我需要将One、Two两个类的实例按指定格式存入JSON,再解析JSON还原为类实例。目前已成功生成JSON,但解析还原时出现编译错误(错误代码含C3867、C2672等)。

错误信息

1>c:\users\212506\documents\visual studio 2015\projects\consoleapplication6\consoleapplication6\consoleapplication6.cpp(72): error C3867: 'One::Value1': non-standard syntax; use '&' to create a pointer to member
...

生成的JSON片段

{ "One",{
            { "Value1", one.Value1() },
        }
        },
{ "Two",{
            { "Value1", two.Value1() },
            { "Value2", two.Value2() }
        }
        },

完整代码

#include "stdafx.h"
#include <iostream>
#include <string>
#include <array>
#include <initializer_list>

#include "nlohmann/json.hpp"
using nlohmann::json;

class Two
{
public:
    Two() :m_Value1(0), m_Value2(0)
    {}

    Two(int val1, int val2) :
        m_Value1(val1), m_Value2(val2)
    {
    }

    int& Value1()
    {
        return m_Value1;
    }
    int& Value2()
    {
        return m_Value2;
    }

public:
    int m_Value1;
    int m_Value2;
};

class One
{
public:
    One() : m_Value1_1(0)
    {}
    One(int val1) : m_Value1_1(val1)
    {
    }
    int& Value1()
    {
        return m_Value1_1;
    }

public:
    int m_Value1_1;
};

std::string ToJsonString(One &one, Two &two)
{
    nlohmann::json j =
    {
        { "One",{
            { "Value1", one.Value1() },
        }
        },
        { "Two",{
            { "Value1", two.Value1() },
            { "Value2", two.Value2() }
        }
        },
    };

    std::cout << j.dump(4) << std::endl;
    std::string str = j.dump(4);
    return str;
}

void from_json(const json& j, One& one) {
    j.at("Value1").get_to(one.Value1());
}

void from_json(const json& j, Two& two) {
    j.at("Value1").get_to(two.Value1());
    j.at("Value2").get_to(two.Value2());
}

void ToObjectsOne(std::string json, One &one1, Two &two1)
{
    nlohmann::json data;
    try
    {
        data = nlohmann::json::parse(json);
    }
    catch (nlohmann::json::exception& exception)
    {
        std::cerr << "Exception[" << exception.what() << "]";
    }

    one1 = data["One"].get<One>();
    two1 = data["Two"].get<Two>();
}


int main()
{
    One one(10);
    Two two(10, 20);

    std::string jsonStr = ToJsonString(one, two);

    One one1;
    Two two1;
    ToObjectsOne(jsonStr, one1, two1);

    std::cout << one1.m_Value1_1<<std::endl;
    std::cout << two1.m_Value1 << std::endl;
    std::cout << two1.m_Value2 << std::endl;
    return 0;
}

核心问题

请问是否可以使用One one = data["One"].get<One>();的方式获取数据?若不行,该如何从JSON中还原这两个类的实例?


问题分析与解决

首先,data["One"].get<One>()这种方式完全可以使用,编译错误的根源在于from_json函数的写法问题:

1. 编译错误原因

错误C3867是因为Visual Studio 2015对模板推导的支持存在缺陷,无法正确识别one.Value1()返回的int&作为get_to的参数;本质上是编译器误将成员函数调用识别为取成员函数指针的语法。

2. 两种修正方案

方案一:直接操作public成员变量(最简洁)

既然类的成员变量是public的,直接在from_json中赋值可以彻底避开函数调用的模板推导问题:

void from_json(const json& j, One& one) {
    one.m_Value1_1 = j.at("Value1").get<int>();
}

void from_json(const json& j, Two& two) {
    two.m_Value1 = j.at("Value1").get<int>();
    two.m_Value2 = j.at("Value2").get<int>();
}

方案二:显式指定get_to的模板参数

如果必须保留成员函数的调用,可以通过显式指定模板参数,帮助编译器正确推导类型:

void from_json(const json& j, One& one) {
    j.at("Value1").get_to<int>(one.Value1());
}

void from_json(const json& j, Two& two) {
    j.at("Value1").get_to<int>(two.Value1());
    j.at("Value2").get_to<int>(two.Value2());
}

3. 额外优化建议

  • 将ToObjectsOne的参数std::string json改为const std::string& json,避免不必要的字符串拷贝;
  • 确保使用的nlohmann/json版本兼容Visual Studio 2015(推荐v3.9.1及更早版本)。

修正后的完整代码(方案一)

#include "stdafx.h"
#include <iostream>
#include <string>
#include <array>
#include <initializer_list>

#include "nlohmann/json.hpp"
using nlohmann::json;

class Two
{
public:
    Two() :m_Value1(0), m_Value2(0)
    {}

    Two(int val1, int val2) :
        m_Value1(val1), m_Value2(val2)
    {
    }

    int& Value1()
    {
        return m_Value1;
    }
    int& Value2()
    {
        return m_Value2;
    }

public:
    int m_Value1;
    int m_Value2;
};

class One
{
public:
    One() : m_Value1_1(0)
    {}
    One(int val1) : m_Value1_1(val1)
    {
    }
    int& Value1()
    {
        return m_Value1_1;
    }

public:
    int m_Value1_1;
};

std::string ToJsonString(One &one, Two &two)
{
    nlohmann::json j =
    {
        { "One",{
            { "Value1", one.Value1() },
        }
        },
        { "Two",{
            { "Value1", two.Value1() },
            { "Value2", two.Value2() }
        }
        },
    };

    std::cout << j.dump(4) << std::endl;
    return j.dump(4);
}

void from_json(const json& j, One& one) {
    one.m_Value1_1 = j.at("Value1").get<int>();
}

void from_json(const json& j, Two& two) {
    two.m_Value1 = j.at("Value1").get<int>();
    two.m_Value2 = j.at("Value2").get<int>();
}

void ToObjectsOne(const std::string& jsonStr, One &one1, Two &two1)
{
    nlohmann::json data;
    try
    {
        data = nlohmann::json::parse(jsonStr);
    }
    catch (const nlohmann::json::exception& exception)
    {
        std::cerr << "Exception[" << exception.what() << "]" << std::endl;
    }

    one1 = data["One"].get<One>();
    two1 = data["Two"].get<Two>();
}


int main()
{
    One one(10);
    Two two(10, 20);

    std::string jsonStr = ToJsonString(one, two);

    One one1;
    Two two1;
    ToObjectsOne(jsonStr, one1, two1);

    std::cout << one1.m_Value1_1 << std::endl;
    std::cout << two1.m_Value1 << std::endl;
    std::cout << two1.m_Value2 << std::endl;
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 02:22:34