【发布时间】:2013-10-23 13:40:52
【问题描述】:
我一直在努力解决这个问题,也许我只是盯着它太久了?
无论如何,手头的问题是找到一种在 C++ 中表示 JSON 的好方法,在您继续阅读之前,请注意我对能够做到这一点的库不感兴趣,所以我想用原始 C 或 C++ 来做(C++11 很好),没有提升,没有 libjson 我知道它们,并且由于这个问题范围之外的原因,我不能(/不会)添加依赖项。
既然已经解决了,让我告诉你一些关于这个问题的信息,以及我到目前为止所做的尝试。
问题是要找到一种在 C++ 中表示 JSON 的好方法,这有点问题的原因是 JSON 是超级松散类型的,而 C++ 是硬类型的。考虑一下 JSON,JSON 真正能够在类型方面做什么?
- 号码(例如
42或3.1415) - 字符串(例如
"my string") - 数组(例如
[],或[1,3.1415,"my string]) - 对象(例如
{}或{42, 3.1415, "my string", [], [1,3.1415, "my string]}
这意味着有两种“原始”类型,Number 和 String,以及两种容器类型 Array 和 对象。原始类型相当简单,而容器类型在 C/C++ 中变得很棘手,因为它们可以并且可能包含不同类型的元素,因此语言中的任何内置类型都不够用,数组不能容纳不同类型的元素。这也适用于 STL 类型(列表、向量、数组等)(除非它们具有多态相等性)。
因此,JSON 中的任何容器都可以容纳任何类型的 json-type,这几乎是它的全部。
我的原型或尝试过的东西以及为什么它不起作用 我第一个天真的想法是只使用模板,所以我设置了一个 json-object 或 json-node 类型,然后使用模板来决定其中的内容,因此它的结构如下:
template <class T>
class JSONNode {
const char *key;
T value;
}
虽然这看起来很有希望,但是当开始使用它时,我意识到当我尝试将节点排序为容器类型(例如数组、向量、unordered_map 等)时遇到了麻烦,因为它们仍然想知道那个 JSONNode 的类型!如果一个节点定义为JSONNode<int>,而另一个节点定义为JSONNode<float>,那么将它们放在容器中将会有问题。
所以我超越了这一点,无论如何我对将它们保存在容器中并不是很感兴趣,我很乐意让它们具有自我意识或称之为什么,即在指向下一个节点的指针中添加广告,但是再次确定节点的类型变得很棘手,而这正是我开始思考多态性的时候。
多态性
让我们创建一个虚拟的 JSONNode 并实现一个 JSONNumberNode, JSONStringNode, JSONArrayNode 和 JSONObjectNode 类型,它们将很好地适合我可能希望它们放入的任何容器,使用多态性让它们都成为 JSONNode。
代码示例可能已经到位。
class JSONNode {
public:
const char *key;
//?? typed value, can't set a type
};
class JSONNumberNode : public JSONNode {
public:
int value;
}
class JSONStringNode : public JSONNode {
public:
const char *value;
}
起初我认为这是要走的路。然而,当我开始思考如何处理值部分时,我意识到我无法访问该值,即使我编写了一个特定的函数来检索该值,它会返回什么?
所以确定我确实有具有不同类型值的对象,但是如果不首先转换为正确的类型,我就无法真正访问它们,所以我可以做一个dynamic_cast<JSONStringNode>(some_node);,但我怎么知道将它转换为什么? RTTI?好吧,我觉得那时它变得有点复杂,我想我可能可以使用 typeof 或 decltype 来确定将其类型转换为什么,但没有成功..
POD 类型
所以我尝试了一些不同的东西,我想争辩说,也许我实际上可以以 pod 的方式做到这一点。然后我会将value 部分设置为void * 并尝试让一些union 跟踪类型。但是,我遇到了与我已经遇到的相同的问题,即如何将数据转换为类型。
我觉得有必要解决这个问题,为什么我没有更深入地研究我使用 POD 所做的尝试......
因此,如果有人给出了如何在 C++ 中表示 JSON 的智能解决方案,我将非常感激。
【问题讨论】:
-
@Ashalynd OP 竭尽全力表示他对外部库不感兴趣。
-
@JBentley 如果纯粹用于学习目的,这个问题是正确的。如果没有,不要重新发明轮子
-
@Manu343726 无关。 OP 并没有就他是否应该重新发明轮子征求意见。他表示这正是他想做的,并正在征求有关如何做的建议。
-
见
boost::variant。如果你想重新发明它,但至少要检查一下设计。
标签: c++ json c++11 collections types