在web开发中经常会在前后端之间通过json传递数据,但是又不能像客户端编程那样直接传递对象。所以json用于将两边的对象编码成数据,再在另一边解码出来。传递的过程中要先构造json对象,再将json对象编码为json字符串,而在接收的一端要先将json字符串解码而json对象
1. ndarray编码为json字符串
import numpy as np
import json
data = np.random.rand(10)
json_obj = {"data": str(data.tolist())}
json_str = json.dumps(json_obj)
注意: ndarray对象必须要使用tolist转为list对象才能转为json对象,因为json.dumps函数并没有对ndarray对象的默认转换,如果不用tolis(),那就要写转换函数,即dumps函数的参数default ()就算写转换函数,在转换函数中还是要用tolist,因为一切高阶对象都需要转化到低阶。
那么,用ndarray对象直接构造json会有什么不同呢
上面的是list,下面的是ndarray,分别转为json对象的区别,一个逗号分割,一个空格分隔,而,使用json.loads函数解码的时候只认识逗号分隔的,除非在loads函数里面注明object_hook参数
如下是完整解码json对象的代码
json_obj_inverse = json.loads(json_str)
data_str_inverse = json_obj_inverse["data"]
print("data_str_inverse = ", data_str_inverse)
print(type(data_str_inverse))
print("++++++++++++++++++++++++++++++++++++++++++")
data_inverse = json.loads(data_str_inverse)
print("data_inverse = ", data_str_inverse)
print(type(data_inverse))
此处有一个细节,即json官方要求json的键和值都是用双引号"“包含,假如不用”"将不会认为是json对象,所以上面将list也包装成了字符串,此处必须再次使用json.loads函数将其解码成list, 如果需要可以进一步转化为ndarray,但是loads函数默认不会解码为ndarray类型的,它只支持了python的基本内置类型
2. 将python自定义对象编码为json
print("++++++++++++++将python对象编码成json字符串++++++++++++++++++++++")
class Person(json.JSONEncoder):
def __init__(self):
self.name = "111"
self.age = 222
def Person_2_json(obj):
return {
"name": obj.name,
"age": obj.age
}
def handle_hook(j):
p = Person()
p.name = j["name"]
p.age = j["age"]
return p
p = Person()
p.name = "David"
p.age = 25
p_json = json.dumps(p, default=Person_2_json, indent=4)
print(p_json)
p_inverse = json.loads(p_json, object_hook=handle_hook)
print("name:", p_inverse.name)
print("age:", p_inverse.age)
如上,自定义类型不是内置的,所以在编码和解码的时候需要分别定义default和object_hook函数
3.多维的ndarray对象编码为json对象
直接使用tolist()将多维ndarray转化为list即可,在json对象中是是以嵌套的json数组存在。
nd = np.random.random_sample(size=(3, 5))
print(nd)
# json.dumps(nd)
np_array_to_list = nd.tolist()
print(np_array_to_list)
json_file = "file.json"
json.dump(np_array_to_list, open(json_file, 'w', encoding='utf-8'), sort_keys=True, indent=4)
*但是一般在web数据传输中不仅要json数组,更多的是json对象,将多维ndarray对象编码为自定义的json对象的方法是使用dumps或者dump的default函数,假如解码的时候还是要原来的ndarray对象同上,定义object_hook函数即可
def nd_2_json(nd):
ndList = nd.tolist()
d = {}
for i, ele in enumerate(ndList):
d[str(i)] = str(ele)
return d
nd_json = json.dumps(nd, default=nd_2_json)
print(nd_2_json(nd))
print("nd_json", nd_json)