jsoncpp v0.5中的一个bug

本文介绍了一个在jsoncpp 0.5版本中存在的类型转换Bug,详细分析了问题的原因,并提供了规避该问题的方法。

本文目的

今天在使用jsoncpp 0.5的时候很偶然的发现了一个bug,由于jsoncpp在业界被广泛使用,所以有必要将这个bug指出。

 

一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
  * bug_demo.cpp
  *
  *  Created on: 2011-11-22
  *      Author: bourneli
  */
#include "json/json.h"
#include <iostream>
#include <fstream>
 
using  namespace  std;
 
int  main()
{
     Json::Value oRootVal;
 
     Json::Reader oJsonReader;
     oJsonReader.parse( "{\"aInt\" : 3}" , oRootVal);
 
     Json::Value oInt = oRootVal[ "aInt" ];
     cout << "aInt : "  << oInt.asInt() << endl;
     if  (oInt.isConvertibleTo(Json::stringValue))
     {
         cout << "aInt as string : "  << oInt.asString() << endl;
     }
     else
     {
         cout << "aInt cannot convert to a string"  << endl;
     }
     return  0;
}

根据上面的代码,如果使用过jsoncpp,应该可以预测输出,如下:

aInt : 3

aInt as string : 3

但是,实际上却是:

clip_image002

抛异常了 囧~~~

 

原因分析

Json::Value::isConvertibleTo函数,从字面意思上看,就是判断当前value是否可以转成目标类型,我们看看Json::Value::isConvertibleTo的源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
bool
Value::isConvertibleTo( ValueType other ) const
{
    switch  ( type_ )
    {
    case  nullValue:
       return  true ;
    case  intValue:
       return  ( other == nullValue  &&  value_.int_ == 0 )
              || other == intValue
              || ( other == uintValue  && value_.int_ >= 0 )
              || other == realValue
              || other == stringValue
              || other == booleanValue;
    case  uintValue:
       return  ( other == nullValue  &&  value_.uint_ == 0 )
              || ( other == intValue  && value_.uint_ <= (unsigned)maxInt )
              || other == uintValue
              || other == realValue
              || other == stringValue
              || other == booleanValue;
    case  realValue:
       return  ( other == nullValue  &&  value_.real_ == 0.0 )
              || ( other == intValue  &&  value_.real_ >= minInt  &&  value_.real_ <= maxInt )
              || ( other == uintValue  &&  value_.real_ >= 0  &&  value_.real_ <= maxUInt )
              || other == realValue
              || other == stringValue
              || other == booleanValue;
    case  booleanValue:
       return  ( other == nullValue  &&  value_.bool_ == false  )
              || other == intValue
              || other == uintValue
              || other == realValue
              || other == stringValue
              || other == booleanValue;
    case  stringValue:
       return  other == stringValue
              || ( other == nullValue  &&  (!value_.string_  ||  value_.string_[0] == 0) );
    case  arrayValue:
       return  other == arrayValue
              ||  ( other == nullValue  &&  value_.map_->size() == 0 );
    case  objectValue:
       return  other == objectValue
              ||  ( other == nullValue  &&  value_.map_->size() == 0 );
    default :
       JSON_ASSERT_UNREACHABLE;
    }
    return  false ; // unreachable;
}

实现很简单,就是一系列的类型转换映射。上面的代码中第13行的地方就说明,int类型的Value是可以转化成string类型的Value。

但是实际上,却抛出了异常,我们可以分析下Json::Value::AsString函数的实现,源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
std::string
Value::asString() const
{
    switch  ( type_ )
    {
    case  nullValue:
       return  "" ;
    case  stringValue:
       return  value_.string_ ? value_.string_ : "" ;
    case  booleanValue:
       return  value_.bool_ ? "true"  : "false" ;
    case  intValue:
    case  uintValue:
    case  realValue:
    case  arrayValue:
    case  objectValue:
       JSON_ASSERT_MESSAGE( false , "Type is not convertible to string"  );
    default :
       JSON_ASSERT_UNREACHABLE;
    }
    return  "" ; // unreachable
}

实现也很简单,也是通过当前value的类型,判断是否可以转成string类型。第12行和第17行表明:转换映射和isConvertibleTo不一致。这就是导致bug的直接原因。

总结

此bug不是什么致命bug,并不能掩盖jsoncpp的跨平台,简单,轻量级等优点,使用的时候需要注意这里,否则会带来问题。所以,建议不要使用isConvertibleTo这个函数,而是通过手动判断当前数据类型,然后使用C++内置的类型转换,就不会出现该问题。

相关资料

下面的链接是jsoncpp在sourceforge官方网站上对该bug的描述

https://sourceforge.net/tracker/index.php?func=detail&aid=3021877&group_id=144446&atid=758826

没有注册的同学无法浏览,这里截个图:

clip_image002[5]

声明:如有转载本博文章,请注明出处。您的支持是我的动力!文章部分内容来自互联网,本人不负任何法律责任。
本文转自bourneli博客园博客,原文链接:http://www.cnblogs.com/bourneli/archive/2011/12/28/2304618.html ,如需转载请自行联系原作者
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值