如何使用 C++ 解析 json 数组?
Posted
技术标签:
【中文标题】如何使用 C++ 解析 json 数组?【英文标题】:How can i parse json arrays with C++? 【发布时间】:2015-11-01 04:00:18 【问题描述】:std::stringstream ss;
ss << " \"values\": \"A\": 1, \"B\": 10 ";
我想把这个流变成下面这个格式。
"values": [
"A": 1, "B": 10
...
]
有人知道如何使用 c++ 解析数组的值并提升 ptree 吗?
【问题讨论】:
你试过什么?例如,您是否尝试拨打read_json
?如果是这样,出了什么问题?如果没有,为什么不呢?
显示您的问题的 SSCCE 在哪里?现在:***.com/search?q=user%3A85371+JSON+array+ 这已被多次询问,并在 JSON 解析器的约 20 行文档中进行了描述
阅读文档。
【参考方案1】:
假设输入input.json
使用 Boost Spirit V2.x
这是一个使用增强精神气的简单方法:
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";
当然,输出还是和之前一样。
【讨论】:
而且我已经完成了 3 个竞争性实施,以过度杀戮的古老传统:live coding session (experiment) 我不想学习@Columbo 说真的,继续努力,很棒的东西! Boost 很强大...非常强大。用你的几行代码,我解决了几个小时的问题......谢谢。【参考方案2】:使用 ThorsSerizlier 和与 sehe 相同的输入。
假设输入input.json
#include "ThorSerialize/JsonThor.h"
#include "ThorSerialize/SerUtil.h"
#include "ThorSerialize/Traits.h"
#include <iostream>
#include <fstream>
struct Data
std::vector<std::map<std::string, int>> values; // The values input
;
ThorsAnvil_MakeTrait(Data, values); // Describes what can be serialized
// There is a definition for all standard
// types in SerUtil.h
int main()
std::ifstream dataStream("input.json");
Data data;
// Automatically reads data into C++ structure.
// Directly from a stream.
dataStream >> ThorsAnvil::Serialize::jsonImport(data);
// Converts a C++ structure into JSON for output to a stream.
std::cout << ThorsAnvil::Serialize::jsonExport(data);
【讨论】:
以上是关于如何使用 C++ 解析 json 数组?的主要内容,如果未能解决你的问题,请参考以下文章