问题:
- 找不到 Qi JSON 解析器中缺少解析属性的原因。解析器成功解析输入字符串,但输出数据结构 json_object 仅包含第一个属性(attribute_a)但缺少其他属性(attribute_b 和 attribute_c)
软件: 使用 Boost 1.52 提升灵气
平台:Windows 7(64 位)
编译器(Visual Studio 2010)
要求:
帮助找出解析器没有找到所有属性的原因。
查看调试输出,我发现属性没有被放入单个 std::vector 对象中。我使用在http://www.json.org/上找到的 JSON 语法作为参考。我希望看到的“ members ”的输出是一个 std::vector ,其中包含为该 JSON 对象找到的所有 json_pair 对象的列表。
限制:
- 解析器不支持 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;
}