【问题标题】:Boost Variant: How to model JSON?Boost Variant:如何对 JSON 建模?
【发布时间】:2011-07-03 07:25:00
【问题描述】:

我正在尝试将使用 Boost Spirit 存储 JSON 对象的 JSON 字符串解析为递归数据结构:

Value <== [null, bool, long, double, std::string, Array, Object];
Array <== [Value, Value, Value, ...];
Object <== ["name1": Value, "name2": Value, ...];

这是我的代码:

#include <map>
#include <vector>
#include <string>
#include <boost/variant.hpp>
#include <boost/shared_array.hpp>
#include <boost/shared_ptr.hpp>

struct JsonNull {};
struct JsonValue;

typedef std::map<std::string, JsonValue *> JsonObject;
typedef std::vector<JsonValue *> JsonArray;

struct JsonValue : boost::variant<JsonNull, bool, long, double, std::string, JsonArray, JsonObject>
{
};

JsonValue aval = JsonObject();

编译时出现错误:

Error C2440: 'initializing' : cannot convert from 'std::map<_Kty,_Ty>' to 'JsonValue'

此外,如何安全地将 JsonValue 转换为 JsonObject?当我尝试这样做时:

boost::get<JsonObject>(aval) = JsonObject();

这会导致运行时异常/致命故障。

非常感谢任何帮助。

编辑:

按照@Nicol 的建议,我得到了以下代码:

struct JsonNull {};
struct JsonValue;

typedef std::map<std::string, JsonValue *> JsonObject;
typedef std::vector<JsonValue *> JsonArray;
typedef boost::variant<
    JsonNull, bool, long, double, std::string,
    JsonObject, JsonArray,
    boost::recursive_wrapper<JsonValue>
> JsonDataValue;

struct JsonValue
{
    JsonDataValue data;
};

我可以像这样简单地处理 JsonObject 和 JsonArray:

JsonValue *pJsonVal = new JsonValue();

boost::get<JsonObject>(pCurrVal->data).insert(
    std::pair<std::string, JsonValue *>("key", pJsonVal)
);

boost::get<JsonArray>(pCurrVal->data).push_back(pJsonVal);

只是为了让每个人都能从中受益而发帖。

【问题讨论】:

    标签: c++ json boost boost-spirit boost-variant


    【解决方案1】:

    您必须使用递归包装器(并且您不应该从 boost::variant 派生):

    struct JsonValue;
    
    typedef boost::variant</*types*/, boost::recursive_wrapper<JsonValue> > JsonDataValue;
    
    struct JsonValue
    {
        JsonDataValue value;
    };
    

    要让 Boost.Spirit 采用 JsonValue,您需要编写其中一个 Fusion 适配器,以将原始变体类型适配到结构中。


    此外,如何安全地将 JsonValue 转换为 JsonObject?当我尝试这样做时:

    这不是变体的工作方式。如果您想将它们设置为一个值,只需像设置任何其他值一样设置它们:

    JsonValue val;
    val.value = JsonValue();
    

    【讨论】:

    • 感谢 Nicol 的及时答复!如您所见,我有 JsonArray 和 JsonObject 类型,在遵循您的路径时如何使用它们?你能更详细地讨论一下吗?谢谢!
    • @Protege:像 Boost 的大多数部分一样,Variant 有非常好的文档。你应该阅读它。这将为我们俩节省很多时间。
    • 我在 Variant 上阅读了很多次,但无法理解。我试图将 std::map 和 std::vector 插入 JsonValue。还是谢谢。
    • 冷静一下,我找到了答案!感谢您的提示!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多