jsoncpp解决序列化顺序按字母排序问题

21 篇文章 0 订阅
5 篇文章 1 订阅

使用场景:需要修改json中key的值,如果使用jsoncpp读取——序列化——修改值——存储,这样的话存的json文件的关键字的顺序就和源文件不是一致的,默认会按照字母进行排序。

使用jsoncpp没有找到合适的方式进行解决,只能借助python进行解决。

python可以指定顺序,在之前已经介绍过:python 读取json格式数据保持原有顺序

我们可以在c++中调用python的函数进行这个操作。

python代码如下:

#! /usr/bin/python2.7
# -*- coding:utf-8 -*-
import json
from collections import OrderedDict

#返回值 -1表示key不存在
#返回值 -2表示打开源文件失败
#返回值 -3表示打开更新文件失败
#返回值 0表示更新成功

def updateJson(jsonFile,jsonNewData,*jsonKey):
    try:
        f = open(jsonFile, "r")
    except IOError:
        return -2
    jsonFileData = json.load(f,object_pairs_hook=OrderedDict)
    #print(json.dumps(jsonFileData,indent = 4))
    jsonKey = list(jsonKey)
    jsonKeyLen = len(jsonKey)
    keyExist = True
    #匹配key是否存在
    for i in range(jsonKeyLen): 
        if i == 0:
            if jsonKey[i] not in jsonFileData:
                keyExist = False
                break
        else:
            if jsonKey[i] not in jsonFileData[jsonKey[i-1]]:
                keyExist = False
                break
    if keyExist == False:
        f.close()
        return -1

    if jsonKeyLen == 1:
        jsonFileData[jsonKey[0]] = jsonNewData
    elif jsonKeyLen == 2:
        jsonFileData[jsonKey[0]][jsonKey[1]] = jsonNewData
    elif jsonKeyLen == 3:
        jsonFileData[jsonKey[0]][jsonKey[1]][jsonKey[2]] = jsonNewData
    elif jsonKeyLen == 4:
        jsonFileData[jsonKey[0]][jsonKey[1]][jsonKey[2]][jsonKey[3]] = jsonNewData
    elif jsonKeyLen == 5:
        jsonFileData[jsonKey[0]][jsonKey[1]][jsonKey[2]][jsonKey[3]][jsonKey[4]] = jsonNewData
    elif jsonKeyLen == 6:
        jsonFileData[jsonKey[0]][jsonKey[1]][jsonKey[2]][jsonKey[3]][jsonKey[4]][jsonKey[5]] = jsonNewData
    elif jsonKeyLen == 7:
        jsonFileData[jsonKey[0]][jsonKey[1]][jsonKey[2]][jsonKey[3]][jsonKey[4]][jsonKey[5]][jsonKey[6]]  = jsonNewData
    elif jsonKeyLen == 8:
        jsonFileData[jsonKey[0]][jsonKey[1]][jsonKey[2]][jsonKey[3]][jsonKey[4]][jsonKey[5]][jsonKey[6]][jsonKey[7]] = jsonNewData
    elif jsonKeyLen == 9:
        jsonFileData[jsonKey[0]][jsonKey[1]][jsonKey[2]][jsonKey[3]][jsonKey[4]][jsonKey[5]][jsonKey[6]][jsonKey[7]][jsonKey[8]] = jsonNewData
    elif jsonKeyLen == 10:
        jsonFileData[jsonKey[0]][jsonKey[1]][jsonKey[2]][jsonKey[3]][jsonKey[4]][jsonKey[5]][jsonKey[6]][jsonKey[7]][jsonKey[8]][jsonKey[9]] = jsonNewData
    f.close()
    try:
        f2 = open(jsonFile, "w")
    except IOError:
        return -3
    jsonStr = json.dumps(jsonFileData,indent = 4)
    #print(jsonStr)
    f2.write(jsonStr)
    f2.close()
    return 0

if __name__ == "__main__":
    print(updateJson("78911.json",False,"openFlag")) 
    print(updateJson("789.json",False,"openFlag22"))   
    print(updateJson("789.json",60,"ID"))  
    print(updateJson("789.json","blue","color","book"))
    print(updateJson("789.json",False,"openFlag"))   

目前这个函数只能修改10层内嵌套key的json,而且采用了一个比较蠢的方法,就是判断可变参数的个数来确定key的嵌套层数。再进行条件执行,等以后找到了统一的写法再进行修改。目前这样也能在工程当中使用。

源json文件:

{
    "ID": 20,
    "longitude": "112.12345",
    "latitude": "28.67890",
    "num": 123,
    "openFlag": true,
    "name": "xi xi",
    "data": [
        4,
        2,
        3,
        4,
        5
    ],
    "color": {
        "book": "red",
        "clothes": "white",
        "trousers": "black"
    }
}

修改之后:

{
    "ID": 60, 
    "longitude": "112.12345", 
    "latitude": "28.67890", 
    "num": 123, 
    "openFlag": false, 
    "name": "xi xi", 
    "data": [
        4, 
        2, 
        3, 
        4, 
        5
    ], 
    "color": {
        "book": "blue", 
        "clothes": "white", 
        "trousers": "black"
    }
}

执行结果:

-2
-1
0
0
0

可以看出,ID、book和openFlag已经修改了。

接下来使用C++调用python代码,注意编译的时候需要连接python库,我这里使用的是2.7版本,所以是  -lpython2.7

#include "../common.h"
#include <jsoncpp/json/json.h>
#include <python2.7/Python.h>

int main()
{
    Py_Initialize();
    ifstream readFile("123.json",ios::binary);
    if(!readFile.is_open())
    {
        printf("open fail\n");
        return -1;
    }
    else
    {
        Json::Reader reader;
        Json::Value root;
        if(reader.parse(readFile,root))  //reader将文件中的内容解析到root
        {
            cout << root << endl;  //结果的显示顺序和文件中并不一致
            cout << "------------------------C++---------------------------" << endl;
            
            //导入环境变量
            PyRun_SimpleString("import sys");  
            PyRun_SimpleString("sys.path.append('./')");  

            //导入模块
            PyObject *pModule = PyImport_ImportModule("testJson");
            if(pModule == NULL)
            {
                printf("NO testJson\n");
            }
            PyObject *pFunc = PyObject_GetAttrString(pModule, "updateJson");
            if(pModule == NULL)
            {
                printf("NO updateJson\n");
            }
            PyObject *args = Py_BuildValue("(sis)","789.json",88,"ID");
            /*这样也是可行的
            PyObject *args = PyTuple_New(3);
            PyTuple_SetItem(args, 0, Py_BuildValue("s","789.json");
            PyTuple_SetItem(args, 1, Py_BuildValue("i",99));
            PyTuple_SetItem(args, 2, Py_BuildValue("s","ID"));
           */

            PyObject *retPython = PyEval_CallObject(pFunc,args); //调用python函数
            int ret = -1;
            PyArg_Parse(retPython, "i",&ret); //把返回值转为C++类型
            printf("ret = %d\n",ret);
            Py_DECREF(pModule);
            Py_DECREF(pFunc);
            Py_DECREF(args);
            Py_DECREF(retPython);
        }
        else
        {
            cout << "no reader" << endl;
        }
        readFile.close();
        
        //释放python,与Py_Initialize()对应
        Py_Finalize();
        return 0;
    }
}

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值