gpt4 book ai didi

c++ - 我如何用 C++ 解析 json 数组?

转载 作者:行者123 更新时间:2023-11-30 00:47:52 26 4
gpt4 key购买 nike

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

我想把这个流变成下面这种格式。

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

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

最佳答案

假设输入 input.json

使用 Boost Spirit V2.x

这里有一个简单的 boost 灵气的方法:

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() 输出相同

使用属性树

这有点不同,我选择不实现 operator>> 因为 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++ - 我如何用 C++ 解析 json 数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33459076/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com