HTTP服务器向我发送JSON响应(字符串),如下所示:
{
"folders" :
[{
"id" : 109,
"parent_id" : 110,
"path" : "\/1\/105\/110\/"
},
{
"id" : 110,
"parent_id" : 105,
"path" : "\/1\/105\/"
}
],
"files" :
[{
"id" : 26,
"parent_id" : 105,
"name" : "picture.png",
"hash" : "md5_hash",
"path" : "\/1\/105\/"
},
{
"id" : 25,
"parent_id" : 110,
"name" : "another_picture.jpg",
"hash" : "md5_hash",
"path" : "\/1\/105\/110\/"
}
]
}
我想将此“远程文件夹的树”与本地文件夹树(例如,包含本地文件位置的字符串向量)进行比较,因此我想在(string,vector(map(string
,string)))(我不知道是否可行)。
我正在开发一种工具来在本地文件夹和远程文件夹之间同步文件,因此我正在使用boost列出本地文件夹,并且我想将本地列表与远程列表(JSON响应)进行比较以生成操作(下载本地文件夹中不存在的丢失文件,上传远程文件夹中不存在的文件)。
有了这个功能,我在另一个问题上发现:
void print(boost::property_tree::ptree const& pt)
{
using boost::property_tree::ptree;
ptree::const_iterator end = pt.end();
for (ptree::const_iterator it = pt.begin(); it != end; ++it)
{
std::cout << it->first << ": " << it->second.get_value<std::string>() << std::endl;
print(it->second);
}
}
我成功打印了以下内容:
folders:
:
id: 109
parent_id: 110
name: 2011_pictures
:
id: 110
parent_id: 105
name: Aminos
files:
id: 26
parent_id: 105
name: logo.png
:
id: 5
parent_id: 109
name: me.jpg
我想知道是否有可能生成此结果a `map<string, vector
`,它将具有2个键:“文件夹”和“文件”,并且使用这2个键,我们可以访问包含每个对象(文件或文件)信息的map类型的向量夹)。如果可行,它将降低任务的复杂性(比较两个文件夹列表)
示例:T [“ folder”] [0] [“ id”]将返回“ 109”; T [“ files”] [0] [“ name”]将返回“
logo.png”
更新:这个问题很旧,但是我想提个建议:每当您想在C ++下处理Json时,请使用RAPIDJSON。
由于另一个答案中的数据结构被认为“非常复杂”,因此建议目标数据结构为:
struct Data {
struct Folder { int id, parent_id; std::string path; };
struct File { int id, parent_id; std::string path, name, md5_hash; };
using Folders = std::vector<Folder>;
using Files = std::vector<File>;
Folders folders;
Files files;
};
但是,如果我们“跳过中间人”并将JSON专门解析为所示Data
结构,则OP可能会更满意。这“简化”了语法,使其仅针对此类文档:
start = '{' >>
(folders_ >> commasep) ^
(files_ >> commasep)
>> '}';
folders_ = prop_key(+"folders") >> '[' >> -(folder_ % ',') >> ']';
files_ = prop_key(+"files") >> '[' >> -(file_ % ',') >> ']';
folder_ = '{' >> (
(prop_key(+"id") >> int_ >> commasep) ^
(prop_key(+"parent_id") >> int_ >> commasep) ^
(prop_key(+"path") >> text_ >> commasep)
) >> '}';
file_ = '{' >> (
(prop_key(+"id") >> int_ >> commasep) ^
(prop_key(+"parent_id") >> int_ >> commasep) ^
(prop_key(+"path") >> text_ >> commasep) ^
(prop_key(+"name") >> text_ >> commasep) ^
(prop_key(+"hash") >> text_ >> commasep)
) >> '}';
prop_key = lexeme ['"' >> lazy(_r1) >> '"'] >> ':';
commasep = &char_('}') | ',';
这个语法允许
优点:
最后一个好处是反面:如果您想读取稍有不同的JSON,现在您需要处理语法,而不仅仅是编写其他提取/转换。
在37行代码中,我偏爱其他答案,但我将由您自己决定。
这是直接使用此语法的相同演示程序:
[Live On Coliru](http://coliru.stacked-crooked.com/a/cbbe576146a96f58)
//#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
static std::string const sample = R"(
{
"folders" :
[{
"id" : 109,
"parent_id" : 110,
"path" : "\/1\/105\/110\/"
},
{
"id" : 110,
"parent_id" : 105,
"path" : "\/1\/105\/"
}
],
"files" :
[{
"id" : 26,
"parent_id" : 105,
"name" : "picture.png",
"hash" : "md5_hash",
"path" : "\/1\/105\/"
},
{
"id" : 25,
"parent_id" : 110,
"name" : "another_picture.jpg",
"hash" : "md5_hash",
"path" : "\/1\/105\/110\/"
}
]
})";
struct Data {
struct Folder { int id, parent_id; std::string path; };
struct File { int id, parent_id; std::string path, name, md5_hash; };
using Folders = std::vector<Folder>;
using Files = std::vector<File>;
Folders folders;
Files files;
};
BOOST_FUSION_ADAPT_STRUCT(Data::Folder, (int,id)(int,parent_id)(std::string,path))
BOOST_FUSION_ADAPT_STRUCT(Data::File, (int,id)(int,parent_id)(std::string,path)(std::string,name)(std::string,md5_hash))
BOOST_FUSION_ADAPT_STRUCT(Data, (Data::Folders,folders)(Data::Files,files))
namespace folder_info { // adhoc JSON parser
template <typename It, typename Skipper = qi::space_type>
struct grammar : qi::grammar<It, Data(), Skipper>
{
grammar() : grammar::base_type(start) {
using namespace qi;
start = '{' >>
(folders_ >> commasep) ^
(files_ >> commasep)
>> '}';
folders_ = prop_key(+"folders") >> '[' >> -(folder_ % ',') >> ']';
files_ = prop_key(+"files") >> '[' >> -(file_ % ',') >> ']';
folder_ = '{' >> (
(prop_key(+"id") >> int_ >> commasep) ^
(prop_key(+"parent_id") >> int_ >> commasep) ^
(prop_key(+"path") >> text_ >> commasep)
) >> '}';
file_ = '{' >> (
(prop_key(+"id") >> int_ >> commasep) ^
(prop_key(+"parent_id") >> int_ >> commasep) ^
(prop_key(+"path") >> text_ >> commasep) ^
(prop_key(+"name") >> text_ >> commasep) ^
(prop_key(+"hash") >> text_ >> commasep)
) >> '}';
prop_key = lexeme ['"' >> lazy(_r1) >> '"'] >> ':';
commasep = &char_('}') | ',';
////////////////////////////////////////
// Bonus: properly decoding the string:
text_ = '"' >> *ch_ >> '"';
ch_ = +(
~char_("\"\\")) [ _val += _1 ] |
qi::lit("\x5C") >> ( // \ (reverse solidus)
qi::lit("\x22") [ _val += '"' ] | // " quotation mark U+0022
qi::lit("\x5C") [ _val += '\\' ] | // \ reverse solidus U+005C
qi::lit("\x2F") [ _val += '/' ] | // / solidus U+002F
qi::lit("\x62") [ _val += '\b' ] | // b backspace U+0008
qi::lit("\x66") [ _val += '\f' ] | // f form feed U+000C
qi::lit("\x6E") [ _val += '\n' ] | // n line feed U+000A
qi::lit("\x72") [ _val += '\r' ] | // r carriage return U+000D
qi::lit("\x74") [ _val += '\t' ] | // t tab U+0009
qi::lit("\x75") // uXXXX U+XXXX
>> _4HEXDIG [ append_utf8(qi::_val, qi::_1) ]
);
BOOST_SPIRIT_DEBUG_NODES((files_)(folders_)(file_)(folder_)(start)(text_))
}
private:
qi::rule<It, Data(), Skipper> start;
qi::rule<It, Data::Files(), Skipper> files_;
qi::rule<It, Data::Folders(), Skipper> folders_;
qi::rule<It, Data::File(), Skipper> file_;
qi::rule<It, Data::Folder(), Skipper> folder_;
qi::rule<It, void(const char*), Skipper> prop_key;
qi::rule<It, std::string()> text_, ch_;
qi::rule<It> commasep;
struct append_utf8_f {
template <typename...> struct result { typedef void type; };
template <typename String, typename Codepoint>
void operator()(String& to, Codepoint codepoint) const {
auto out = std::back_inserter(to);
boost::utf8_output_iterator<decltype(out)> convert(out);
*convert++ = codepoint;
}
};
boost::phoenix::function<append_utf8_f> append_utf8;
qi::uint_parser<uint32_t, 16, 4, 4> _4HEXDIG;
};
template <typename Range, typename It = typename boost::range_iterator<Range const>::type>
Data parse(Range const& input) {
grammar<It> g;
It first(boost::begin(input)), last(boost::end(input));
Data parsed;
bool ok = qi::phrase_parse(first, last, g, qi::space, parsed);
if (ok && (first == last))
return parsed;
throw std::runtime_error("Remaining unparsed: '" + std::string(first, last) + "'");
}
}
int main()
{
auto parsed = folder_info::parse(sample);
for (auto& e : parsed.folders)
std::cout << "folder:\t" << e.id << "\t" << e.path << "\n";
for (auto& e : parsed.files)
std::cout << "file:\t" << e.id << "\t" << e.path << "\t" << e.name << "\n";
}
输出:
folder: 109 /1/105/110/
folder: 110 /1/105/
file: 26 /1/105/ picture.png
file: 25 /1/105/110/ another_picture.jpg
一个HTTP服务器发送给我一个JSON响应(一个字符串),如下所示: 我想将这个“远程文件夹的树”与本地文件夹树(例如包含我的本地文件的位置的字符串向量)进行比较,所以我想在(string,vector ( map(string,string))(我不知道这是否可能)的地图上转换这个JSON。 我正在开发一个工具来同步本地和远程文件夹之间的文件,因此我正在使用boost列出本地文件夹,并且我想将本
我有一个这样的文件: [data.json] 如何通过解析此文件创建粒子向量。据我所知,我需要使用boop读取文件并将字符串(行)读入向量,然后解析向量的内容。 类粒子是这样的: 该类中省略了其他用于 get/set 的方法。 基本上,我想帮助创建一个
问题内容: 我目前正在尝试使用boost-asio的套接字API通过网络将一些JSON数据从客户端传输到服务器。我的客户基本上是这样做的: 在服务器端,我可以选择各种功能。我想使用JsonCpp解析接收到的数据。在研究JsonCpp API(http://jsoncpp.sourceforge.net/class_json_1_1_reader.html)时,我发现Reader可以在char数组或
我是Boost和Json新手。应该很简单,但是我找不到答案。 如何使用Boost读取C中字符串向量的值。 Json文件的内容例如: 最后,我想为每个关键字向量:
本文向大家介绍使用boost读取XML文件详细介绍,包括了使用boost读取XML文件详细介绍的使用技巧和注意事项,需要的朋友参考一下 boost读取XML文件 boost中提供了对配置文件读取的支持,它就是:property_tree。 basic_ptree 是property_tree的核心基础。其接口像std::list。可以执行很多基本的元素操作,比如使用begin()、end(
问题内容: 我正在尝试从JSON文件读取值到数组以进行进一步处理。我正在使用JSON-Smart 1.2.0库。由于某些限制,我不能使用2.0版本。 我收到以下异常。 我什至尝试使用JSONArray而不是JSONObject。我在这儿做错了什么?这是读取JSON内容的正确方法吗? 以下是Java代码。 以下是json文件的内容。 问题答案: 您的JSON包含一个具有单个对象元素的数组,因此您应该