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

enum ValueType {
nullValue = , ///< '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 = -;
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[]={} ;
sprintf(strVal,"%s, %s, %d, %s, %s", msg_.c_str(), code_.c_str(), data1, strValue1.c_str(), strValue2.c_str());
return ;
}

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

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAASUAAAAzCAYAAADRnx5FAAAElElEQVR4nO3cPW7qWhiF4XWu7gA8BidSJMoUnoGdgooiPSU0RxRQMAKKpIjS+JT0p6BKEZiBC0qkSInH4BncWwCJcfwX/8AmeR8pSoyx2d42K9+2Db+iKPpPAGCIf07dAACII5QAGIVQAmAUQgmAUXJDKfQ9jVbxR1Yaeb7CdtsE4Af7lX31LZTvPepyIt3ezrPX0P+r6MFtp3UAfpzsSil81qLTles+KIqi3c9f9Z2Z1u/T0UEghb4na7TSamTJOiyxPuZ7vvyRJc+n3gLwWWYohc8L6epC24rJkmVZsqxbzYOprq3ddHwoF/oaLHpaP7hyu31p/qTDWAr1vAjUnww1fFirtxiIXAKQlBFKKz1Og9i0o9k6Vh1FkaL1TE58icepOpOhbElyu+prrqd4KoXPWgR9dV1JsjWcdDR9/FxNAfjZUkMp9O+0ceKRE2h6va+Wdj/XU33EVqjXjbMtrCRJrrbF0kfohM8LBf2u3gd7F1dyNq/bSiv05VkelROA9FB6U0+TXvyRokrpTS9BR5f2xxLu75mc9yHcbujWjZ0Qty/VCV701uTWADh7qaHkDoe6OHikoFIKX7Vxrg6XsW/Uc3ZDuIOh296FrpyNXkNJ9lDLaKmhLQA/XMmbJwsqpdSqx9ZNz9H8afV56CYprboCgJKhVHROSZJ2VU+MfdOTM7/TYCHNfifuZQpftXn/m3NKALaaqZTkqtsP9JI8QWTfqOcECtTTTbIientJqZ4A/HSZd3SHvqeBeupMp8q5n1tyZlovh7JDX95A+rPc3RaQK5S/fTLnkQAcyPmYydeFvqfrl0nhx05WI0t3V2stSSQACY2GEgDUxVeXADAKoQTAKIQSAKMQSgCMQigBMMq/aQ+Ox+NjtwMAJGWEkiTd398fsx0AIOkIwzfLsgr/BoC9zEoprkyARFGU+bhlWQfzk9MAsFcqlJIBUiZUkkG2n07+Tlt/HVlty3u9NubV0XRo12lnUVvy+juvv9LaU6Wv66yzTV/dh8c+Pk1+P5QKparKNOwYw7i8Sq2NeXXb2qQ67azalrzlsl67Tl9nhdC5VOjHPj5Nfz+0FkrxxuY9p40Kw9SDr4x9+5tcX1ttyZrX9DbkMTF0OF9aT+lQqrPDi4ZTOD/xfwBfXW6v7PFkQtCUVbVf8KFypZTs9KLzDjit/T449Ru8TGVTVJ2dahvyKkM0p3IoVfkvd4wDigBMlzX2r6LqOvKWiVcXWZVG3use49gqc3GHgKqv1RPdWQdWXFM78VxOan4XeSeU85YpCqaqy5qiSr/gUKuhJOVXSnmhdc47s41tqLrOouqiyjrbuupY9kpOU9We1Ow+KnOsn/NxfSyth1KWJq/cxO99ii+/n06uM3k5ue15dbal7jrz2lm1LUXzy25D1rymLoy0tY+KFPVb0qmPz7bnfVXq1+GOx+P3z759Zcc1Meb+DiVvG9vwHfrFJPSnuQorpbbK22O83qm0sQ3foV9MQn+ai+9TAmAUQgmAUQglAEYhlAAYhVACYBRCCYBRCCUARiGUABiFUAJgFEIJgFEIJQBGIZQAGOV/C/NG7I+HCxAAAAAASUVORK5CYII=" alt="" />

jsoncpp动态解析节点类型的更多相关文章

  1. C#匿名类型和动态解析减少定义传输类模板

    C#作为强类型语言,在序列化和反序列化(json)场景中对字符串解析常常需要定义强类型模板,造成编码上的繁琐.其实可以使用匿名类型和动态解析减少json序列化时候的数据模板定义: string a = ...

  2. 深入理解DOM节点类型第七篇——文档节点DOCUMENT

    × 目录 [1]特征 [2]快捷访问 [3]文档写入 前面的话 文档节点document,隶属于表示浏览器的window对象,它表示网页页面,又被称为根节点.本文将详细介绍文档节点document的内 ...

  3. jquery 源码解析 节点遍历

    jquery遍历,用于根据其相对于其他元素的关系来查找或选取html元素,以某项选择开始,并沿着这个选择移动,知道移动被称为对dom进行遍历 ☑ <div> 元素是 <ul> ...

  4. DOM Element节点类型详解

    上文中我们讲解了 DOM 中最重要的节点类型之一的 Document 节点类型,本文我们继续深入,谈谈另一个重要的节点类型 Element . 1.概况 Element 类型用于表现 HTML 或 X ...

  5. Mybatis 系列6-结合源码解析节点配置:objectFactory、databaseIdProvider、plugins、mappers

    [Mybatis 系列10-结合源码解析mybatis 执行流程] [Mybatis 系列9-强大的动态sql 语句] [Mybatis 系列8-结合源码解析select.resultMap的用法] ...

  6. Mybatis 系列4-结合源码解析节点:typeAliases

    [Mybatis 系列10-结合源码解析mybatis 执行流程] [Mybatis 系列9-强大的动态sql 语句] [Mybatis 系列8-结合源码解析select.resultMap的用法] ...

  7. 使用Newtonsoft.Json.dll(JSON.NET)动态解析JSON、.net 的json的序列化与反序列化(一)

    在开发中,我非常喜欢动态语言和匿名对象带来的方便,JSON.NET具有动态序列化和反序列化任意JSON内容的能力,不必将它映射到具体的强类型对象,它可以处理不确定的类型(集合.字典.动态对象和匿名对象 ...

  8. 深入理解DOM节点类型第五篇——元素节点Element

    × 目录 [1]特征 [2]子节点 [3]特性操作[4]attributes 前面的话 元素节点Element非常常用,是DOM文档树的主要节点:元素节点是html标签元素的DOM化结果.元素节点主要 ...

  9. 深入理解DOM节点类型第一篇——12种DOM节点类型概述

    × 目录 [1]元素 [2]特性 [3]文本[4]CDATA[5]实体引用[6]实体名称[7]处理指令[8]注释[9]文档[10]文档类型[11]文档片段[12]DTD 前面的话 DOM是javasc ...

随机推荐

  1. DDD领域驱动之干货(三)完结篇!

    首先这里发一下结构图,因为是重写的,但是代码都是一样所有如下: 这里我先说一下看了大部分的DDD文章都是采用的WCF做服务,这里呢我用的是webapi做服务,WCF和WEBAPI的区别可以去百度下. ...

  2. java 与操作系统进程同步问题(一)————互斥问题

    最近学校开设了操作系统原理课程,老师要求用任意语言去模拟进程的同步和互斥问题. 在尝试的写了之后,发现这个问题非常有意思,故想记录在博客中,作为自己的学习轨迹. 个人还是比较喜欢用Java语言,所以采 ...

  3. Java 8——Optional

    本文主要介绍Java 8的 Optional 的简单使用 Address 1 2 3 4 5 6 7 @Data @AllArgsConstructor @NoArgsConstructor publ ...

  4. 深入分析Java的String类的方法与特点

    字符串是任何编程语言都必须支持的变量类型,有些编程语言是直接提供了原生的变量类型,有些编程语言则使用语法特性以 SDK 的形式提供支持.在Java编程平台中,对字符串的支持使用了后者的形式,就是通过在 ...

  5. 浅谈Ubuntu PowerShell——小白入门教程

    早在去年八月份PowerShell就开始开源跨平台了,但是一直没有去尝试,叫做PowerShell Core. 这里打算简单介绍一下如何安装和简单使用,为还不知道PowerShell Core on ...

  6. 纯手工打造简单分布式爬虫(Python)

    前言 这次分享的文章是我<Python爬虫开发与项目实战>基础篇 第七章的内容,关于如何手工打造简单分布式爬虫 (如果大家对这本书感兴趣的话,可以看一下 试读样章),下面是文章的具体内容. ...

  7. Bash提示符

    Bash有四种提示符 1.基本提示符(PS1):即$符号,是默认的基本提示符,当Shell运行在交互模式下时,该提示符会出现在屏幕上,可以设置为其它符号. 显示PS1设置[cb@cb:16:36:23 ...

  8. C语言中指针和数组的区别

    看<C专家编程>一书,看到数组与指针并不相同一章,遂做了一段测试: 代码: #include <stdio.h> #include <stdlib.h> int m ...

  9. scrapy抓取淘宝女郎

    scrapy抓取淘宝女郎 准备工作 首先在淘宝女郎的首页这里查看,当然想要爬取更多的话,当然这里要查看翻页的url,不过这操蛋的地方就是这里的翻页是使用javascript加载的,这个就有点尴尬了,找 ...

  10. PHPUnit-函数依赖-数据提供-异常-忽略-自动生成

    1. 本文目的 本文目的是收录一些PHPUnit的有用技巧,这些技巧能够为给PHPUnit单元测试带来很多便利.本文将要介绍的技巧如下: 函数依赖测试 数据提供函数 异常测试 跳过忽略测试 自动生成测 ...