加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

关于jsoncpp内部排序的问题

发布时间:2020-12-16 19:51:30 所属栏目:百科 来源:网络整理
导读:使用jsoncpp创建文件的时候,跟添加的顺序不相同,它是按照字母表给排序过的。 虽然问题没有解决,但是找到一篇很好的文章http://wff8785.blog.163.com/blog/static/8920227020109179151766/ json内部存储object元素是用map存储的,map的特性就是会对每次ins

使用jsoncpp创建文件的时候,跟添加的顺序不相同,它是按照字母表给排序过的。

虽然问题没有解决,但是找到一篇很好的文章http://wff8785.blog.163.com/blog/static/8920227020109179151766/




json内部存储object元素是用map存储的,map的特性就是会对每次insert入的<key,value>值,按照key排序,这就要求key的类型具有<号的重载(key的类型是class)。Json::Value内部存储对象类型是用map:<CZString,Value>,CZString 是Value内部定义的字符串类型,并对<小于号做了重载。

那目前我遇到的问题是,我要在value中插入的object对象会被安装key排序,但是我又不希望它安装key排序,我要它按照我输入的顺序给我输出。昨天纠结这个问题一天,本来以为有两个解决办法,但是我一直尝试的那个是行不通的。

方法一:修改"<"号的的重载函数,让它始终返回true。本来兴高采烈的以为要成功了,发现结果输出的顺序是对了,可是每个key对应的值却变成了NULL。猛然反应过来,原来CZString的"<"不是map在insert的时候才调用,其他时候也是有用的。失败~~~

方法二:禁止insert调用"<"重载函数。map类的声明函数是类似这样的:map(key,value,function),function的默认函数是operator <(),当然,在STL中这些是用模版写好的,我还没研究过这个。知道这个方法了,可是还不知道怎么去折腾它。

昨天在这个问题上纠结了很久,基本上吃饭想着它 睡觉想着它 坐车想着它 走路也想着它……不过是问题总会有解决办法的。现在的问题是,我要去研究下map的声明函数是个怎么回事,还有template这个东西。

今天星期天,小妹过来鸟,又要开始奔波的一天了。

===========================

问题终于解决了,经过的一天的纠结,原来就那么简单~~~

class Value

{

……

public:

class JSON_API DisCmp {
public:
bool operator()(const CZString& s1,const CZString& s2) const {
return true; //不做任何处理,直接返回
}
};

//typedef std::map<CZString,Value> ObjectValues; 这个是原来的对象类型的声明函数

typedef std::map<CZString,Value,DisCmp> ObjectValues; //这个是新的,用DisCmp禁用insert排序

……

}

以上,就完成了禁用了往map中插入元素的排序功能的任务。但是这个时候问题其实还没解决,而也是这个问题让我纠结了大半天。因为这个时候我输出的结果是按照我原来的插入顺序了,可是输出地值却仍然全是null。

于是顺着这个思路下去,根据输出结果,排序的问题是解决了,而且也没有调用<号的重载,说明是赋值的时候发生问题。因为我的整个思考深度就只到这里,所以就开始怀疑源码的正确性,很显然,最后我错了……

多亏xiaop的提醒,最后才发现可能是最后输出时候的问题。Writer类输出的时候是根据下标操作符[]进行定位数据的,而在Value中重载[]的实现,是find函数来查找。为什么find()有问题呢?

原来map内部存储数据是用红黑树算法的,那map::find()函数查找值的时候也是根据红黑树的模式进行查找的。而我禁用了insert元素时候的排序功能,就破坏了这种结构,这个时候还用find()查找的话,当然就找不到值了。我的解决办法是,改成了使用遍历,方法如下: const Value & Value::operator[]( const char *key ) const { JSON_ASSERT( type_ == nullValue || type_ == objectValue ); if ( type_ == nullValue ) return null; #ifndef JSON_VALUE_USE_INTERNAL_MAP CZString actualKey( key,CZString::noDuplication ); //wangff---- //ObjectValues::const_iterator it = value_.map_->find( actualKey ); //由于map::find()函数是根据红黑树特性进行查找的,重写了map的insert比较方法之后, //便破坏了其内部的红黑树特性,因此,这里将find函数改成用遍历查找 ObjectValues::const_iterator it; for (it=value_.map_->begin(); it!=value_.map_->end(); it++) { if (it->first == actualKey) break; } //---------------------- if ( it == value_.map_->end() ) return null; return (*it).second; #else const Value *value = value_.map_->find( key ); return value ? *value : null; #endif }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读