• jsoncpp动态解析节点类型


       在互联网无处不在的今天,JSON作为轻量级数据存储格式,被广泛应用到互联网数据传输中。众所周知,JSON由键/值对、对象、数组组成,其中键/值对的值包括以下几种类型:

    enum ValueType {
      nullValue = 0, ///< 'null' value
      intValue,      ///< signed integer value
      uintValue,     ///< unsigned integer value
      realValue,     ///< double value
      stringValue,   ///< UTF-8 string value
      booleanValue,  ///< bool value
      arrayValue,    ///< array value (ordered list)
      objectValue    ///< object value (collection of name/value pairs).
    };

      如果在发送方和接收方间约定JSON数据格式中数据类型固定不变,那么不存在需要动态去判断节点数据类型并解析的问题。但是在实际应用过程中,存在两种情况需要支持JSON数据类型动态解析:第一,发送方因为平台迁移等种种原因导致的数据类型变化,比如本来为"key":200的键值对变成了"key":"200",这个时候如果还是按照intValue去获取key的值的话,就会解析失败; 第二,接收方不愿意一个个去按照数据类型去解析JSON数据的时候,想动态去获取数据,比如"key":20,按照stringValue和intValue都能正确的解析。

      针对以上情况,本文基于jsoncpp设计了一个动态解析JSON数据的类,主要包括两个函数:

    DynamicGetValue:支持解析int,uint,double,bool以及前三种类型的stringValue形式,当遇到"key":"1.23"键值对后,该函数就会进入Json::stringValue语句,通过atof函数保持了数据的精度
    DynamicGetStrValue:支持解析stringValue类型以及DynamicGetValue函数支持的数据类型,在调用DynamicGetValue模板函数时,是使用的double实例化,目的是为了保证不丢失数据精度
    template<typename T>
    bool DynamicGetValue(Json::Value &value, T &&sValue){ //获取json int、uint、bool、double类型的值的值
        bool result = true;
        switch(value.type()){
        case Json::stringValue:
            sValue = atof(value.asString().c_str());
            break;
        case Json::int64Value:
            sValue = value.asInt();
            break;
        case Json::uint64Value:
            sValue = value.asUInt();
            break;
        case Json::booleanValue:
            sValue = value.asBool();
            break;
        case Json::realValue:
            sValue = value.asDouble();
            break;
        default:
            result = false;
            break;
        }
        return result;
    }
    

    bool DynamicGetStrValue(Json::Value &value,string &sValue){ //获取json string、int、uint、bool、double的值 bool result = true; double nValue = -1; if(value.type() == Json::stringValue){ sValue = value.asString(); } else if(DynamicGetValue<double&>(value, nValue)){ sprintf((char*)sValue.data(),"%.8f", nValue); } else{ result = false; } return result;
    }

       针对上动态数据类型解析函数,设计了如下测试试用例,这里我们把strJson数据中的"data1":1,"data2":3.1415927两个键值对当做stringValue类型来解析,能够正确的获取数据。但是切记,不能将"msg"和"code"调用DynamicGetValue解析,因为它们只能用stringValue来表达,只能调用DynamicGetStrValue解析,所以这里DynamicGetStrValue是万能的,能解析任何类型的数据。

    int main(){
        string strJson = "{\"msg\":\"正常\", \"code\":\"A0000\", \"data1\":1,\"data2\":3.1415927, \"data3\":-4}";
        Json::Reader reader;
        Json::Value root;
        Json::Value value;
        if (!reader.parse(strJson, root, false))
        {
            return;
        }
        string msg_,code_,strValue1,strValue2;
        unsigned int data1;
        double data2;
        int data3;
        if(root.isMember("msg")){
            value = root["msg"];
            DynamicGetStrValue(value,msg_);
        }
        if(root.isMember("code")){
            value = root["code"];
            DynamicGetStrValue(value,code_);
        }
        if(root.isMember("data1")){
            value = root["data1"];
            DynamicGetValue(value,data1);
        }
        if(root.isMember("data2")){
            value = root["data2"];
            DynamicGetStrValue(value,strValue1);
        }
        if(root.isMember("data3")){
            value = root["data3"];
            DynamicGetStrValue(value, strValue2);
        }
        char strVal[100]={0}    ;
        sprintf(strVal,"%s, %s, %d, %s, %s", msg_.c_str(), code_.c_str(), data1, strValue1.c_str(), strValue2.c_str());
        return 1;
    }    

       上测试用例输出如下图,正确的获取了data1和data2的值,达到了动态解析JSON数据类型的目的。

  • 相关阅读:
    CoreJava逻辑思维-顺时针打印自定义矩阵
    微信公众号开发引言
    .Net自动更新程序GeneralUpdate,适用于wpf,winfrom,控制台应用
    .net技术栈转型心路历程分享
    TCP/IP网络编程之数据包协议
    TCP/IP网络编程之字节序和网络字节序
    TCP/IP网络编程之socket交互流程
    Linux入门笔记
    WPF新手快速入门系列 3.MVVM
    WPF新手快速入门系列 2.绑定
  • 原文地址:https://www.cnblogs.com/chenyangchun/p/6953132.html
Copyright © 2020-2023  润新知