最近在做一个NLU相关的项目,需要对json文件进行读取,wins vs2008环境,需要引入第三方库json.h,需要工程导入jsoncpp的静态数据连接库json_vc71_libmtd.lib,详细的教程可以自行百度。在输出的json文件我发现不是按着list添加顺序的,它是按照字母表给排序过的, json内部存储object元素是用map存储的,map的特性就是会对每次insert入的<key,value>值,按照key排序,这就要求key的类型具有<号的重载(key的类型是class)。Json::Value内部存储对象类型是用map:<CZString, Value>,CZString 是Value内部定义的字符串类型,并对<小于号做了重载。
方法:禁止insert调用"<"重载函数
添加一下方法
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。map内部存储数据是用红黑树算法的,那map::find()函数查找值的时候也是根据红黑树的模式进行查找的。而我禁用了insert元素时候的排序功能,就破坏了这种结构,这个时候还用find()查找的话,当然就找不到值了。把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
}