前言
养成一个好的习惯只需要坚持21天,Day14
什是JSON?
JSON是轻量级的文本数据交换格式,指的是 JavaScript 对象表示法(JavaScript Object Notation),类似XML但又比 XML 更小、更快,更易解析。
JSON语法
JSON数据的书写格式是:"名称":“值”
,例如:
"name":"汤姆"
JSON的值可以是:数字、字符串、逻辑值、数组、对象和null。
{"age":30}
{"name":"汤姆","country":"England"}
{"flag":true}
{"money":null}
JSON数组:
{
"sites": [
{ "name":"汤姆" , "country":"England "},
{ "name":"张三" , "country“:”China" },
{ "name":"里斯" , "country":"France" }
]
}
JSON与Python对象
在Python的内部有json模块,提供了Python对象到JSON格式的转换。
把Python对象编程一个JSON:
>>> import json
>>> d = dict(name='Bob',age=20,score=90)
>>> json.dumps(d)
# '{"name": "Bob", "age": 20, "score": 90}'
json.dumps()
方法返回一个str
,内容是标准的JSON。类似的,dump()
方法可以直接把JSON写入一个file-like Object
,file-like Object
是像open()
函数返回的这种有个read()
方法的对象,除了file外,还可以是内存的字节流,网络流,自定义流等等。
把JSON反序列化为Python对象:
>>> json_str = '{"name": "Bob", "age": 20, "score": 90}'
>>> json.loads(json_str)
# {'name': 'Bob', 'age': 20, 'score': 90}
json.loads()
函数把JSON的字符串反序列化,json.load()
函数从file-like Object
中读取字符串并反序列化。
JSON进阶
Python的dict
对象可以直接序列化为JSON的{}
,对于我们使用class表示对象时,我们不能直接对类的实例进行序列化,会出现TypeError
错误:
import json
class Student(object):
def __init__(self,name,age,score):
self.name = name
self.age = age
self.score = score
s = Studrnt('Bob',20,90)
print(json.dumps(s))
# Traceback (most recent call last):
...
# TypeError: <__main__.Student object at 0x10603cc50> is not JSON serializable
json模块中的dumps()
方法还提供了许多可选参数,可选参数default
就是把任意一个对象变成一个可序列为JSON
的对象,我们只需要为Student
专门写一个转换函数,再把函数传进去即可:
def student2dict(std):
return {
'name': std.name,
'age': std.age,
'score': std.score
接下来运行:
>>> print(json.dumps(s, default=student2dict))
# {"age": 20, "name": "Bob", "score": 88}
Student
实例s
首先被student2dict()
函数转换成dict,然后再被顺利序列化为JSON。
如果换一个类,比如Teacher类,我们就无法再用此方法进行转化,每次都编写一个转换函数太麻烦了。
通常class的实例都有一个__dict__
属性,它就是一个__dict__
,用来存储实例变量。也有少数例外,定义了__slots__
的class就没有__dict__
属性。
print(json.dumps(s, default=lambda obj: obj.__dict__))
练习
对中文进行JSON序列化时,json.dumps()
提供了一个ensure_ascii
参数,观察该参数对结果的影响:
>>> obj = dict(name='小明', age=20)
>>> s = json.dumps(obj, ensure_ascii=True)
>>> s
# '{"name": "\\u5c0f\\u660e", "age": 20}'
>>> obj = dict(name='小明', age=20)
>>> s = json.dumps(obj, ensure_ascii=False)
>>> s
# '{"name": "小明", "age": 20}'
由上面的运行结果可知,想输出真正的中文需要指定ensure_ascii=False
,这是因为json.dumps()
序列化时对中文默认使用的ascii编码。