微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

用于在C中表示JSON的数据类型

我一直在试图将这个数据看成一段时间,也许我只是盯着太久了?

无论如何,现在的问题是找到一个很好的方式来表示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给定这个信息,我将永远感激.

解决方法

你的最后两个解决方案都可以工作.您的两个问题似乎都在提取实际值,所以让我们来看一下例子.我将介绍POD的想法,因为使用polymorphy确实需要RTTI的简单原因是哪个IMHO是丑陋的.

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

原文地址:https://www.jb51.cc/c/113894.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐