无论如何,现在的问题是找到一个很好的方式来表示JSON,并且在您读取之前,请注意,我对图书馆不感兴趣,所以我想在原始的C或C(C 11是不错的),没有提升,没有libjson我知道他们,由于这个问题的范围之外的原因我不能(/ wont)添加依赖关系.
现在已经清理了,让我告诉你一些关于这个问题,我已经尝试了这么远.
问题是找到一个很好的方式来表示JSON在C中,这是一个有点有问题的原因是JSON是超级松散的类型,而C是非常困难的类型.考虑JSON一秒钟,什么是JSON真的能够类似的?
>号码(例如42或3.1415)
>字符串(例如“我的字符串”)
> Array(例如[]或[1,3.1415,“我的字符串”))
>对象(例如{}或{42,“我的字符串”,[],[1,“我的字符串”}}
那么这意味着有两个“raw”类型,Number和String以及两个容器类型Array和Object.原始类型是相当简单的,而容器类型在C/C++中变得棘手,因为它们可能并且可能包含不同类型的元素,因此,任何内置的语言类型都不够,数组不能保持不同类型的元素.这也适用于STL类型(列表,向量,数组等),(除非它们具有多态等式).
所以JSON中的任何容器都可以容纳任何类型的json类型,这几乎都是它的一部分.
我原型,或尝试,为什么它不工作
我的第一个天真的想法是使用模板,所以我设置一个json对象或json节点类型,然后使用模板来决定它的内容,因此它将具有如下结构:
template <class T> class JSONNode { const char *key; T value; }
虽然这似乎是有希望的,但是当开始使用它时,我意识到当我尝试将节点排序成容器类型(如数组,unordered_map等)时遇到麻烦,因为他们仍然想知道该JSONNode的类型!如果一个节点被定义为JSONNode< int>而另一个是JSONNode< float>那么将它们放在容器中将是有问题的.
所以我转过去,我不是都有兴趣把它们保存在一个容器里,我会很高兴让他们自我意识或称之为,即广告指向下一个节点,但再次弄清楚节点的类型变得棘手,就在这里,我开始思考多态.
多态性
让我们制作一个虚拟JSONNode并实现一个JSONNumberNode,JSONStringNode,JSONArrayNode和JSONObjectNode类型,并且它们将很好地适应我想要的任何容器,使用多态来让它们都是JSONNodes.
代码的一个例子可能在于.
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方式这样做.然后我将设置值部分为void *并尝试有一些工会跟踪类型.但是我收到与我已经有同样的问题,即如何将数据转换为类型.
我觉得需要包装这个问题,为什么我没有深入我用POD尝试过的东西..
所以如果任何人有一个聪明的解决方案,如何表示JSON在C给定这个信息,我将永远感激.
解决方法
JSON:
{ "foo":5 }
你加载这个JSON文件,你会得到的只是你的POD“包装器”.
json_wrapper wrapper = load_file("example.json");
现在你假设你加载的JSON节点是一个JSON对象.你现在必须处理两种情况:它是一个对象,还是不是对象.如果不是,您可能会遇到错误状态,因此可以使用异常.但是如何提取对象本身?好吧,只需要一个函数调用.
try { JsonObject root = wrapper.as_object(); } catch(JSONReadException e) { std::cerr << "Something went wrong!" << std::endl; }
现在如果由包装器包装的JSON节点确实是一个JSON对象,那么可以继续尝试{块,无论你想对对象做什么.同时,如果JSON是“格式错误的”,你可以进入catch(){block.
在内部你会实现这样的东西:
class JsonWrapper { enum NodeType { Object,Number,... }; NodeType type; union { JsonObject object; double number }; JsonObject as_object() { if(type != Object) { throw new JSONReadException; } else { return this->object; } }