gpt4 book ai didi

c++ - 找不到 Qi JSON 解析器中缺少已解析属性的原因

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:29:18 24 4
gpt4 key购买 nike

问题:

  1. 找不到 Qi JSON 解析器中缺少已解析属性的原因。解析器成功解析了输入字符串,但输出数据结构 json_object 仅包含第一个属性 (attribute_a) 而缺少其他属性(attribute_b 和 attribute_c)

软件:使用Boost 1.52 boost 灵气

平台:Windows 7(64 位)

编译器(Visual Studio 2010)

请求:

  1. 帮助找出解析器未找到所有属性的原因。

  2. 查看调试输出,我发现属性没有被放入单个 std::vector 对象中。我正在使用在 http://www.json.org/ 上找到的 JSON 语法作为引用。我希望看到“成员”的输出是单个 std::vector,其中包含为该 JSON 对象找到的所有 json_pair 对象的列表。

限制:

  1. 解析器不支持 Unicode 字符串。

代码:

    #define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_container.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/variant/recursive_variant.hpp>

#include <boost/make_shared.hpp>

#include <vector>

namespace signal_processing {
namespace parsing {

struct json_object;
struct json_array;

typedef boost::variant < std::string,
double,
boost::recursive_wrapper<json_object>,
boost::recursive_wrapper<json_array>,
bool > json_value;

typedef boost::tuple < std::string, json_value> json_pair;

struct json_members
{
std::vector < json_pair > items;
};

struct json_object
{
std::vector < json_members > children;
};

struct json_array
{
std::vector < json_value > list;
};

using boost::spirit::qi::bool_;
using boost::spirit::qi::char_;
using boost::spirit::qi::double_;
using boost::spirit::qi::eol;
using boost::spirit::qi::float_;
using boost::spirit::qi::int_;
using boost::spirit::qi::lexeme;
using boost::spirit::qi::lit;
using boost::spirit::qi::space;
using boost::spirit::qi::_val;
using boost::spirit::qi::_1;

template <typename Iterator, typename Skipper>
struct json_grammar : boost::spirit::qi::grammar < Iterator, json_object(), Skipper>
{
json_grammar() : json_grammar::base_type(object)
{
object = '{' > *members > '}';

pair = string > ':' > value;

members = pair > *( ',' > members );

element_list = '[' > *elements > ']';

elements = value > *( ',' > elements );

value = string |
number |
object |
element_list |
bool_ |
lit("null");

char const* exclude = " ();\"\n\r\t";
string = '"'
> +lexeme[char_ - char_(exclude)]
> '"';

// Return: double
number = double_ |
float_ |
int_;

BOOST_SPIRIT_DEBUG_NODE(object);
BOOST_SPIRIT_DEBUG_NODE(pair);
BOOST_SPIRIT_DEBUG_NODE(members);
BOOST_SPIRIT_DEBUG_NODE(element_list);
BOOST_SPIRIT_DEBUG_NODE(elements);
BOOST_SPIRIT_DEBUG_NODE(value);
BOOST_SPIRIT_DEBUG_NODE(string);
BOOST_SPIRIT_DEBUG_NODE(number);
}

boost::spirit::qi::rule < Iterator, json_object(), Skipper > object;
boost::spirit::qi::rule < Iterator, json_pair(), Skipper > pair;
boost::spirit::qi::rule < Iterator, json_members(), Skipper > members;
boost::spirit::qi::rule < Iterator, json_array(), Skipper > element_list;
boost::spirit::qi::rule < Iterator, json_array(), Skipper > elements;
boost::spirit::qi::rule < Iterator, json_value(), Skipper > value;
boost::spirit::qi::rule < Iterator, std::string(), Skipper > string;
boost::spirit::qi::rule < Iterator, double(), Skipper > number;
};
}
}

BOOST_FUSION_ADAPT_STRUCT(
signal_processing::parsing::json_object,
(std::vector < signal_processing::parsing::json_members >, children)
)

BOOST_FUSION_ADAPT_STRUCT(
signal_processing::parsing::json_members,
(std::vector < signal_processing::parsing::json_pair >, items)
)

BOOST_FUSION_ADAPT_STRUCT(
signal_processing::parsing::json_array,
(std::vector < signal_processing::parsing::json_value >, list)
)

void parse ( std::string const& file )
{
typedef signal_processing::parsing::json_grammar < std::string::const_iterator, boost::spirit::ascii::space_type > configuration_grammar;
configuration_grammar input; // Input grammar
signal_processing::parsing::json_object parsed_data;

std::string::const_iterator iter = file.begin();
std::string::const_iterator end = file.end();
bool r = boost::spirit::qi::phrase_parse ( iter, end, input, boost::spirit::ascii::space, parsed_data );

if ( ! r || iter != end)
{
// Report the next 30 characters
std::string::const_iterator some = iter + 30;

if ( some > end )
{
some = end;
}

std::string context(iter, some);
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "stopped at: \": " << context << "...\"\n";
std::cout << "-------------------------\n";
}
}

int main(int,char**)
{
std::string input ( "{\r\n \"Event\": {\r\n \"attribute_a\": 0.0002,\r\n \"attribute_b\": 2e-005,\r\n \"attribute_c\": 0.022\r\n }\r\n}" );

parse ( input );

return 0;
}

最佳答案

解析器

第一个问题的答案通常是,可能有几种方法可以实现您想要的。具体来说,我可以向您展示一种似乎有效的方法。

关键是为匹配给定短语或标记的一个或多个实例的规则正确设置属性类型,方法是确保您实际声明的是一个容器,而不是一个具有成员的结构是一个容器。

完成后,您需要编写规则,以便 Qi 知道您正在处理一个容器,并且它应该适本地回填。

首先查看成员规则:您将其作为规则提供:

members = pair > *( ',' > members );

我不认为这本身足以告诉 Qi 你想让它用 pair 回填一个 json_members 容器,尤其是因为 pairmember 没有相同的属性类型。所以我建议您将规则替换为:

members = pair > *( ',' > pair );

甚至:

members = pair % ',';

您需要确定这些规则是否等同于同一件事,但您明白了。

关于 json_members 类型:我更改了您的结构定义,使结构派生自容器,而不是将容器作为结构的属性:

struct json_members : std::vector < json_pair > {};

而且您不需要对结构进行 fusion 。

在我看来,这是您的代码的工作版本:

#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_container.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/variant/recursive_variant.hpp>

#include <boost/make_shared.hpp>

#include <vector>

namespace signal_processing {
namespace parsing {

struct json_object;
struct json_array;

typedef boost::variant < std::string,
double,
boost::recursive_wrapper<json_object>,
boost::recursive_wrapper<json_array>,
bool > json_value;

typedef boost::tuple < std::string, json_value> json_pair;

// struct json_members
// {
// std::vector < json_pair > items;
// };
//
// struct json_object
// {
// std::vector < json_members > children;
// };
//
// struct json_array
// {
// std::vector < json_value > list;
// };

struct json_members : std::vector < json_pair > {};
struct json_object : std::vector < json_members > {};
struct json_array : std::vector < json_value > {};

using boost::spirit::qi::bool_;
using boost::spirit::qi::char_;
using boost::spirit::qi::double_;
using boost::spirit::qi::eol;
using boost::spirit::qi::float_;
using boost::spirit::qi::int_;
using boost::spirit::qi::lexeme;
using boost::spirit::qi::lit;
using boost::spirit::qi::space;
using boost::spirit::qi::_val;
using boost::spirit::qi::_1;

template <typename Iterator, typename Skipper>
struct json_grammar : boost::spirit::qi::grammar < Iterator, json_object(), Skipper>
{
json_grammar() : json_grammar::base_type(object)
{
object = '{' > *members > '}';

pair = string > ':' > value;

members = pair > *( ',' > pair );

element_list = '[' > *elements > ']';

elements = value > *( ',' > value );

value = string |
number |
object |
element_list |
bool_ |
lit("null");

char const* exclude = " ();\"\n\r\t";
string = '"'
> +lexeme[char_ - char_(exclude)]
> '"';

// Return: double
number = double_ |
float_ |
int_;

BOOST_SPIRIT_DEBUG_NODE(object);
BOOST_SPIRIT_DEBUG_NODE(pair);
BOOST_SPIRIT_DEBUG_NODE(members);
BOOST_SPIRIT_DEBUG_NODE(element_list);
BOOST_SPIRIT_DEBUG_NODE(elements);
BOOST_SPIRIT_DEBUG_NODE(value);
BOOST_SPIRIT_DEBUG_NODE(string);
BOOST_SPIRIT_DEBUG_NODE(number);
}

boost::spirit::qi::rule < Iterator, json_object(), Skipper > object;
boost::spirit::qi::rule < Iterator, json_pair(), Skipper > pair;
boost::spirit::qi::rule < Iterator, json_members(), Skipper > members;
boost::spirit::qi::rule < Iterator, json_array(), Skipper > element_list;
boost::spirit::qi::rule < Iterator, json_array(), Skipper > elements;
boost::spirit::qi::rule < Iterator, json_value(), Skipper > value;
boost::spirit::qi::rule < Iterator, std::string(), Skipper > string;
boost::spirit::qi::rule < Iterator, double(), Skipper > number;
};
}
}

// BOOST_FUSION_ADAPT_STRUCT(
// signal_processing::parsing::json_object,
// (std::vector < signal_processing::parsing::json_members >, children)
// )
//
// BOOST_FUSION_ADAPT_STRUCT(
// signal_processing::parsing::json_members,
// (std::vector < signal_processing::parsing::json_pair >, items)
// )
//
// BOOST_FUSION_ADAPT_STRUCT(
// signal_processing::parsing::json_array,
// (std::vector < signal_processing::parsing::json_value >, list)
// )

void parse ( std::string const& file )
{
typedef signal_processing::parsing::json_grammar < std::string::const_iterator, boost::spirit::ascii::space_type > configuration_grammar;
configuration_grammar input; // Input grammar
signal_processing::parsing::json_object parsed_data;

std::string::const_iterator iter = file.begin();
std::string::const_iterator end = file.end();
bool r = boost::spirit::qi::phrase_parse ( iter, end, input, boost::spirit::ascii::space, parsed_data );

if ( ! r || iter != end)
{
// Report the next 30 characters
std::string::const_iterator some = iter + 30;

if ( some > end )
{
some = end;
}

std::string context(iter, some);
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "stopped at: \": " << context << "...\"\n";
std::cout << "-------------------------\n";
}
}

int main(int,char**)
{
std::string input ( "{\r\n \"Event\": {\r\n \"attribute_a\": 0.0002,\r\n \"attribute_b\": 2e-005,\r\n \"attribute_c\": 0.022\r\n }\r\n}" );

parse ( input );

return 0;
}

哪些输出:

localhost stov # ./stov
<object>
<try>{\r\n "Event": {</try>
<members>
<try>\r\n "Event": {\r</try>
<pair>
<try>\r\n "Event": {\r</try>
<string>
<try>\r\n "Event": {\r</try>
<success>: {\r\n </success>
<attributes>[[E, v, e, n, t]]</attributes>
</string>
<value>
<try> {\r\n </try>
<string>
<try> {\r\n </try>
<fail/>
</string>
<number>
<try> {\r\n </try>
<fail/>
</number>
<object>
<try>{\r\n "</try>
<members>
<try>\r\n "a</try>
<pair>
<try>\r\n "a</try>
<string>
<try>\r\n "a</try>
<success>: 0.0002,\r\n </success>
<attributes>[[a, t, t, r, i, b, u, t, e, _, a]]</attributes>
</string>
<value>
<try> 0.0002,\r\n </try>
<string>
<try> 0.0002,\r\n </try>
<fail/>
</string>
<number>
<try> 0.0002,\r\n </try>
<success>,\r\n "</success>
<attributes>[0.0002]</attributes>
</number>
<success>,\r\n "</success>
<attributes>[0.0002]</attributes>
</value>
<success>,\r\n "</success>
<attributes>[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002]]</attributes>
</pair>
<pair>
<try>\r\n "a</try>
<string>
<try>\r\n "a</try>
<success>: 2e-005,\r\n </success>
<attributes>[[a, t, t, r, i, b, u, t, e, _, b]]</attributes>
</string>
<value>
<try> 2e-005,\r\n </try>
<string>
<try> 2e-005,\r\n </try>
<fail/>
</string>
<number>
<try> 2e-005,\r\n </try>
<success>,\r\n "</success>
<attributes>[2e-05]</attributes>
</number>
<success>,\r\n "</success>
<attributes>[2e-05]</attributes>
</value>
<success>,\r\n "</success>
<attributes>[[[a, t, t, r, i, b, u, t, e, _, b], 2e-05]]</attributes>
</pair>
<pair>
<try>\r\n "a</try>
<string>
<try>\r\n "a</try>
<success>: 0.022\r\n }\r\n</success>
<attributes>[[a, t, t, r, i, b, u, t, e, _, c]]</attributes>
</string>
<value>
<try> 0.022\r\n }\r\n}</try>
<string>
<try> 0.022\r\n }\r\n}</try>
<fail/>
</string>
<number>
<try> 0.022\r\n }\r\n}</try>
<success>\r\n }\r\n}</success>
<attributes>[0.022]</attributes>
</number>
<success>\r\n }\r\n}</success>
<attributes>[0.022]</attributes>
</value>
<success>\r\n }\r\n}</success>
<attributes>[[[a, t, t, r, i, b, u, t, e, _, c], 0.022]]</attributes>
</pair>
<success>\r\n }\r\n}</success>
<attributes>[[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002], [[a, t, t, r, i, b, u, t, e, _, b], 2e-05], [[a, t, t, r, i, b, u, t, e, _, c], 0.022]]]</attributes>
</members>
<members>
<try>\r\n }\r\n}</try>
<pair>
<try>\r\n }\r\n}</try>
<string>
<try>\r\n }\r\n}</try>
<fail/>
</string>
<fail/>
</pair>
<fail/>
</members>
<success>\r\n}</success>
<attributes>[[[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002], [[a, t, t, r, i, b, u, t, e, _, b], 2e-05], [[a, t, t, r, i, b, u, t, e, _, c], 0.022]]]]</attributes>
</object>
<success>\r\n}</success>
<attributes>[[[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002], [[a, t, t, r, i, b, u, t, e, _, b], 2e-05], [[a, t, t, r, i, b, u, t, e, _, c], 0.022]]]]</attributes>
</value>
<success>\r\n}</success>
<attributes>[[[E, v, e, n, t], [[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002], [[a, t, t, r, i, b, u, t, e, _, b], 2e-05], [[a, t, t, r, i, b, u, t, e, _, c], 0.022]]]]]</attributes>
</pair>
<success>\r\n}</success>
<attributes>[[[[E, v, e, n, t], [[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002], [[a, t, t, r, i, b, u, t, e, _, b], 2e-05], [[a, t, t, r, i, b, u, t, e, _, c], 0.022]]]]]]</attributes>
</members>
<members>
<try>\r\n}</try>
<pair>
<try>\r\n}</try>
<string>
<try>\r\n}</try>
<fail/>
</string>
<fail/>
</pair>
<fail/>
</members>
<success></success>
<attributes>[[[[[E, v, e, n, t], [[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002], [[a, t, t, r, i, b, u, t, e, _, b], 2e-05], [[a, t, t, r, i, b, u, t, e, _, c], 0.022]]]]]]]</attributes>
</object>

统一码

我知道 boost::spirit 的 SVN 构建现在支持 UTF8;尝试使用谷歌搜索 BOOST_SPIRIT_UNICODE。您现在可以使用库中的宽字符串支持来支持“unicode”(微软称之为)。

免责声明

我在 Linux 上工作。 YMMV.

关于c++ - 找不到 Qi JSON 解析器中缺少已解析属性的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14462098/

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