首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >找不到齐JSON解析器中缺少解析属性的原因

找不到齐JSON解析器中缺少解析属性的原因
EN

Stack Overflow用户
提问于 2013-01-22 15:29:28
回答 2查看 600关注 0票数 2

问题

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

软件:使用Boost 1.52提升精神之气

Platform:Windows 7(64位)

编译器 (Visual 2010)

请求

  1. 帮助找出解析器没有找到所有属性的原因。
  2. 查看调试输出,我发现这些属性没有被放入单个std::vector中。我使用在http://www.json.org/上找到的JSON语法作为参考。作为“成员”的输出,我想看到的是一个包含为该JSON对象找到的所有json_pair对象的列表的std::vector。

限制

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

代码:

代码语言:javascript
运行
复制
    #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;
    }
EN

回答 2

Stack Overflow用户

发布于 2013-01-22 17:40:48

解析器

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

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

一旦您这样做了,您就需要编写规则,以便齐知道您正在处理的是一个容器,并且它应该在适当的情况下返回fill。

首先查看成员规则:您提供了以下规则:

代码语言:javascript
运行
复制
members = pair > *( ',' > members );

我不相信这本身就足以告诉齐,您希望它用pair来填充一个pair容器,特别是因为pairs和members不具有相同的属性类型。所以我建议你把这条规则改为:

代码语言:javascript
运行
复制
members = pair > *( ',' > pair );

甚至:

代码语言:javascript
运行
复制
members = pair % ',';

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

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

代码语言:javascript
运行
复制
struct json_members : std::vector < json_pair > {};

你不需要做结构的融合化。

在我看来,下面是您代码的一个工作版本:

代码语言:javascript
运行
复制
#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;
    }

其中产出:

代码语言:javascript
运行
复制
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>

Unicode

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

免责声明

我正在做Linux的工作。YMMV

票数 1
EN

Stack Overflow用户

发布于 2013-04-26 02:43:13

我碰巧写了精神v2中的一种支持UNICODE的JSON解析器,下面是一个解析您的示例的试验案例

代码语言:javascript
运行
复制
#include <sstream>
#include "JSON.hpp"

// util
static JSON::Value roundtrip(JSON::Value const& given) {
    return JSON::parse(to_wstring(given));
}

void roundtrip_test()
{
    auto 
        document = JSON::readFrom(std::istringstream(
                    "{\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}")),
        verify = roundtrip(document);

    std::cout << verify << "\n";
    std::cout << "document <=> verify equal:     \t" << std::boolalpha << (document == verify)                       << "\n";
    std::cout << "document <=> verify text match:\t" << std::boolalpha << (to_string(document) == to_string(verify)) << "\n";
}

这些指纹:

代码语言:javascript
运行
复制
{"Event":{"attribute_a":0.0002,"attribute_b":2e-05,"attribute_c":0.022}}
document <=> verify equal:      true
document <=> verify text match: true

一些更多的API示例:

  1. 对象初始化表达式,用于“立即”JSON文档: void initializer_test() {使用命名空间JSON;const arr { L"text",42,Object { L"dummy",Null() } };auto radius = as_double(arr1);auto const document = Object { L"number“、314e-2 }、{ L"string”、L“hello\n别”}、{ L"array“、arr }、{ L"bool”、False() }、{ L" radius“、radius }、{ L"area”、radius ** 3.14 },{字符串{ 10,L'=‘},字符串{ 10,L’} };std::cout << documentL"bool“<< std::endl;std::cout << documentL”<< std::endl;std:cout << documentL“字符串”<< std::endl;std:cout << documentL“数组”<< std::endl;std::cout << documentL bool“<< std::endl;std::cout << documentL"radius”<< std::endl;std::cout documentL"area“std:endl;cout <<文档<< std::endl;}
  2. 通过往返测试的这个样本输入: {“图像”:{“宽度”:800,“高度”:600,“标题”:“从15楼查看”,“缩略图”:{“俄文”:“Наберегупустынныхволн”,“Escape”:"Ha \“0431\u0435\u0440\u0435\u0433\u0443\”显示\r\b\n“,"http://www.example.com/image/481989943"“:"берегу":”берегу“:125,”宽度“:"100”},“ID”:116,943,234,38793 }}
  3. 此访问者示例转换了一些JSON节点:如何操作JSON树的叶子
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14462098

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档