ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

我如何用C解析json数组?

2019-10-02 11:10:03  阅读:138  来源: 互联网

标签:c json boost


std::stringstream ss;
ss << "{ \"values\": \"A\": 1, \"B\": 10 }";

我想在下面将此流格式化为此格式.

{
  "values": [
    { "A": 1, "B": 10 }
    ...
  ]
}

有人知道如何使用c和boost ptree解析数组的值吗?

解决方法:

假设输入input.json

使用Boost Spirit V2.x

这是一个使用Boost Spirit Qi的简单方法:

Live On Coliru

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_match.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <fstream>
#include <map>

namespace {
    using Element = std::map<std::string, int>;
    struct Array : std::vector<Element> { };

    std::istream& operator>>(std::istream& is, Array& into) {
        using namespace boost::spirit::qi;
        using it = boost::spirit::istream_iterator;

        rule<it, std::string()> s;
        rule<it, Element(), space_type> r, e;

        s = '"' >> ~char_('"') >> '"';
        r = (s >> ':' >> int_) % ',';
        e = '{' >> r >> '}';

        return is >> phrase_match('{'
                    >> lit("\"values\"") >> ':' >> '[' >> (e % ',') >> ']'
                >> '}', space, into);
    }
}

int main() {
    std::ifstream ifs("input.json");
    ifs.unsetf(std::ios::skipws);

    Array array;
    if (ifs >> array) {
        std::cout << "Parsed " << array.size() << " elements:\n";

        for (auto& e : array) {
            std::cout << "\n--------------------\n{ ";
            for (auto& kv : e)
                std::cout << "\"" << kv.first << "\": " << kv.second << ", ";
            std::cout << " }\n";
        }
    } else {
        std::cout << "Parsing failed\n";
    }
}

打印

std::istream& {anonymous}::operator>>(std::istream&, {anonymous}::Array&)
Parsed 13 elements:
--------------------
{ "A": 1, "B": 10,  }
--------------------
{ "C": 3, "D": 12,  }
--------------------
{ "E": 5, "F": 14,  }
--------------------
{ "G": 7, "H": 16,  }
--------------------
{ "I": 9, "J": 18,  }
--------------------
{ "K": 11, "L": 20,  }
--------------------
{ "M": 13, "N": 22,  }
--------------------
{ "O": 15, "P": 24,  }
--------------------
{ "Q": 17, "R": 26,  }
--------------------
{ "S": 19, "T": 28,  }
--------------------
{ "U": 21, "V": 30,  }
--------------------
{ "W": 23, "X": 32,  }
--------------------
{ "Y": 25, "Z": 34,  }

使用Spirit X3

相同的交易:

Live On Coliru

namespace {
    using Element = std::map<std::string, int>;
    struct Array : std::vector<Element> { };

    namespace parser {
        using namespace boost::spirit::x3;
        rule<struct rule_key_t, std::string> s;
        rule<struct rule_element_t, Element> r;
        rule<struct rule_braced_t, Element>  e;

        auto s_def = '"' >> ~char_('"') >> '"';
        auto r_def = (s >> ':' >> int_) % ',';
        auto e_def = '{' >> r >> '}';

        BOOST_SPIRIT_DEFINE(s,r,e)
    }

    std::istream& operator>>(std::istream& is, Array& into) {
        using namespace parser;

        boost::spirit::istream_iterator f(is), l;

        if (!phrase_parse(f, l, '{'
                    >> lit("\"values\"") >> ':' >> '[' >> (e % ',') >> ']'
                >> '}', space, into))
        {
            is.setstate(is.rdstate() | std::ios::failbit);
        }

        return is;
    }
}

具有相同main()的相同输出

使用属性树

这有点不同,我选择不实现运算符>>因为Boost Property并不能真正承担这一点.

Live On Coliru

#include <boost/property_tree/json_parser.hpp>
#include <fstream>
#include <iostream>
#include <map>

namespace {
    using Element = std::map<std::string, int>;
    struct Array : std::vector<Element> { };

    Array read(std::string fname) {
        std::ifstream ifs(fname);
        Array into;

        using namespace boost::property_tree;
        ptree pt;
        read_json(ifs, pt);

        for (auto& entry : pt.get_child("values")) {
            Element e;
            for (auto& property : entry.second)
                e[property.first] = property.second.get_value(0);
            into.push_back(std::move(e));
        }

        return into;
    }
}

int main() {
    try {
        auto array = read("input.json");
        std::cout << "Parsed " << array.size() << " elements:\n";

        for (auto& e : array) {
            std::cout << "--------------------\n{ ";
            for (auto& kv : e)
                std::cout << "\"" << kv.first << "\": " << kv.second << ", ";
            std::cout << " }\n";
        }
    } catch (...) {
        std::cout << "Parsing failed\n";
    }
}

当然,输出再次与之前相同.

标签:c,json,boost
来源: https://codeday.me/bug/20191002/1842711.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有