Boost 变体:如何建模 JSON?

发布于 2024-11-18 03:32:36 字数 1842 浏览 2 评论 0原文

我正在尝试使用 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);

只需发布,以便每个人都可以从中受益。

I'm trying to parse JSON string using Boost Spirit store JSON object into recursive data structures:

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

And here's my code:

#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();

When compiling I get the error:

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

Moreover, how to safely cast JsonValue to JsonObject? When I try doing:

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

This gets run-time exception/fatal failure.

Any help is greatly appreciated.

EDIT:

Following @Nicol's advice, I came out with the following code:

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;
};

I can work on JsonObject & JsonArray as easy as this:

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);

Just posting so that everyone could benefit from this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半﹌身腐败 2024-11-25 03:32:36

您必须使用递归包装器(并且您不应该从 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();

You have to use a recursive wrapper (and you shouldn't be deriving from boost::variant):

struct JsonValue;

typedef boost::variant</*types*/, boost::recursive_wrapper<JsonValue> > JsonDataValue;

struct JsonValue
{
    JsonDataValue value;
};

To make Boost.Spirit take a JsonValue, you will need to write one of those Fusion adaptor things to adapt the raw variant type into a struct.


Moreover, how to safely cast JsonValue to JsonObject? When I try doing:

That's not how variants work. If you want to set them to a value, just set them like any other value:

JsonValue val;
val.value = JsonValue();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文