Json序列化(及其问题)

1. 将字典序列化为json文件

def save_to_json(dict, out_path):
    dict_json = json.dumps(dict)
    f = open(out_path, 'w')
    f.write(dict_json)
    f.close()

2. 加载json文件

def get_json_data(json_path):
    with open(json_path) as f:
        data = json.load(f)
    return data

3. 序列化问题—TypeError:array is not json serializable

将字典序列化为json文件过程中,可能遇到上述问题,原因是字典中某些value为np.array

  • 正确示例(未使用array作为value)
a = [1,2,3]
# b = np.array(a)
dict = {"1": "string","2": 1024,"3": a,
    # "4": b
}
dict_json = json.dumps(dict)
f = open("../dyh_res/tmp.json", 'w')
f.write(dict_json)
f.close()

在这里插入图片描述

  • 错误示例(使用array作为value)
a = [1,2,3]
b = np.array(a)
dict = {"1": "string","2": 1024,"3": a,
    "4": b
}
dict_json = json.dumps(dict)
f = open("../dyh_res/tmp.json", 'w')
f.write(dict_json)
f.close()

在这里插入图片描述

4. 解决方案:.tolist()

(1)简易版

即在序列化前将array转为list,加载时候再转回array

dict = {"1": "string","2": 1024,"3": a,
    "4": b.tolist()
}

在这里插入图片描述

with open("../dyh_res/tmp.json") as f:
    data = json.load(f)
    print(data)
data['4'] = np.array(data['4'])
print(data)

在这里插入图片描述

(2)加强版

上述方法需要对字典中每个array都手动tolist,不如干脆写一个class来解决~

# 编码类
class NumpyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.ndarray):
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)
a = [1,2,3]
b = np.array(a)
dict = {"1": b,"2": b,"3": b,"4": b}
dict_json = json.dumps(dict, cls=NumpyEncoder)  # 调用编码类
# 保存数据
f = open("../dyh_res/tmp.json", 'w')
f.write(dict_json)
f.close()
# 加载数据
with open("../dyh_res/tmp.json") as f:
    data = json.load(f)
    print(data)
for key,value in data.items():  # 按照具体需要,恢复ndarray
    if isinstance(value, list):
        data[key] = np.array(value)
print(data)

在这里插入图片描述

(3)附:该编码类的详尽版本

class NumpyEncoder(json.JSONEncoder):
    """ Special json encoder for numpy types """
    def default(self, obj):
        if isinstance(obj, (np.int_, np.intc, np.intp, np.int8,
            np.int16, np.int32, np.int64, np.uint8,
            np.uint16, np.uint32, np.uint64)):
            return int(obj)
        elif isinstance(obj, (np.float_, np.float16, np.float32, 
            np.float64)):
            return float(obj)
        elif isinstance(obj,(np.ndarray,)): #### This is the fix
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)

参考: stackoverflow

发布了52 篇原创文章 · 获赞 4 · 访问量 2141

猜你喜欢

转载自blog.csdn.net/qq_42191914/article/details/103835293