数据的存储——Json文件存储

以下文字介绍主要引用崔庆才老师文章:https://germey.gitbooks.io/python3webspider/content/5.1.2-Json%E6%96%87%E4%BB%B6%E5%AD%98%E5%82%A8.html

JSON简介

Json,全称为 JavaScript Object Notation, 也就是 JavaScript 对象标记,通过对象和数组的组合来表示数据,构造简洁但是结构化程度非常高,它是一种轻量级的数据交换格式,本节我们来了解一下利用 Python 保存数据到 Json 文件的方法。

1. 对象和数组

在 JavaScript 语言中,一切都是对象。因此,任何支持的类型都可以通过 Json 来表示,例如字符串、数字、对象、数组等。但是对象和数组是比较特殊且常用的两种类型。

  • 对象,对象在 JavaScript 中是使用花括号 {} 包裹起来的内容,数据结构为 {key1:value1, key2:value2, ...} 的键值对结构。在面向对象的语言中,key 为对象的属性,value 为对应的值。键名可以使用整数和字符串来表示。值的类型可以是任意类型。
  • 数组,数组在 JavaScript 中是方括号 [] 包裹起来的内容,数据结构为 ["java", "javascript", "vb", ...] 的索引结构。在 JavaScript 中,数组是一种比较特殊的数据类型,它也可以像对象那样使用键值对,但还是索引使用得多。同样,值的类型可以是任意类型。

所以一个 Json 对象可以写为如下形式:

[{
    "name": "Bob",
    "gender": "male",
    "birthday": "1992-10-18"
}, {
     "name": "Selina",
    "gender": "female",
    "birthday": "1995-10-18"
}]

由中括号包围的就相当于列表类型,列表的每个元素可以是任意类型,在示例中它是字典类型,由大括号包围。

Json 可以由以上两种形式自由组合而成,可以无限次嵌套,结构清晰,是数据交换的极佳方式。

2. 读取Json

Python 为我们提供了简单易用的 json 库来供我们实现 Json 文件的读写操作,我们可以调用 json 库的 loads() 方法将 Json 文本字符串转为 Json 对象,可以通过 dumps()方法将 Json 对象转为文本字符串。

例如在这里有一段 Json 形式的字符串,它是 str 类型,我们用 Python 将可其转换为可操作的数据结构,如列表或字典。

import json
str='''
    [{
    "name": "Bob",
    "gender": "male",
    "birthday": "1992-10-18"
}, {
     "name": "Selina",
    "gender": "female",
    "birthday": "1995-10-18"
}]
'''
print(type(str))
data=json.loads(str)
print(type(data))
print(data)


结果是:
<class 'str'>
<class 'list'>
[{'name': 'Bob', 'gender': 'male', 'birthday': '1992-10-18'}, {'name': 'Selina', 'gender': 'female', 'birthday': '1995-10-18'}]

通过中括号加 0 索引我们可以拿到第一个字典元素,然后再调用其键名即可得到相应的键值。在获取键值的时候有两种方式,一种是中括号加键名,另一种是 get() 方法传入键名。推荐使用 get() 方法来获取内容,这样如果键名不存在的话不会报错,会返回None。另外 get() 方法还可以传入第二个参数即默认值,我们用一个示例感受一下:

print(data[0]['name'])
print(data[0].get('name'))
print(data[0].get('age'))
print(data[0].get('age',25))


结果是:
Bob
Bob
None
25

在上面我们尝试获取年龄 age,其实在原字典中是不存在该键名的,如果不存在,默认会返回 None,如果传入第二个参数即默认值,那么在不存在的情况下则返回该默认值。

值得注意的是 Json 的数据需要用双引号来包围,不能使用单引号。也就是

都是双引号。

否则

import json
str = '''
[{
    'name': 'Bob',
    'gender': 'male',
    'birthday': '1992-10-18'
}]
'''

data=json.loads(str)
print(data)

运行结果会报错

Traceback (most recent call last):
  File "F:/python/python学习/人工智能/第一阶段day2/sever.py", line 10, in <module>
    data=json.loads(str)
  File "D:\anoconda\lib\json\__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "D:\anoconda\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "D:\anoconda\lib\json\decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 3 column 5 (char 8)

遇到这种情况,可以将单引号的str写入一个1.json文件中,然后读取出来即可,

自己按照老师的方法没有重复出来。

3. 输出Json

另外我们还可以调用 dumps() 方法来将 Json 对象转化为字符串。

例如我们将刚上例中的列表重新写入到文本。

import json
data = [{
    'name': 'Bob',
    'gender': 'male',
    'birthday': '1992-10-18'
}]
with open('1.json','w')as f:
    f.write(json.dumps(data))

利用 dumps() 方法我们可以将 Json 对象转为字符串,然后再调用文件的 write() 方法即可写入到文本,结果如下所示:

[{"name": "Bob", "gender": "male", "birthday": "1992-10-18"}]

另外如果我们想保存 Json 的格式,可以再加一个参数 indent,代表缩进字符个数。

import json
data = [{
    'name': 'Bob',
    'gender': 'male',
    'birthday': '1992-10-18'
}]
with open('1.json','w')as f:
    f.write(json.dumps(data,indent=2))

输出结果为,可见得到的内容会自动带有缩进,格式会更加清晰。

[
  {
    "name": "Bob",
    "gender": "male",
    "birthday": "1992-10-18"
  }
]

另外如果 Json 中包含中文字符,例如我们将之前的 Json 的部分值改为中文,再用之前的方法写入到文本。

import json
data = [{
    'name': '王伟',
    'gender': '',
    'birthday': '1992-10-18'
}]
with open('1.json','w')as f:
    f.write(json.dumps(data,indent=2))

得到的中文结果为 Unicode 字符

[
  {
    "name": "\u738b\u4f1f",
    "gender": "\u7537",
    "birthday": "1992-10-18"
  }
]

可以指定ensure_ascii 为 False,且规定文件输出的编码为utf-8

import json
data = [{
    'name': '王伟',
    'gender': '',
    'birthday': '1992-10-18'
}]
with open('1.json','w',encoding='utf-8')as f:
    f.write(json.dumps(data,indent=2,ensure_ascii=False))

结果为

[
  {
    "name": "王伟",
    "gender": "",
    "birthday": "1992-10-18"
  }
]

 

posted @ 2019-05-25 19:24  舒畅123  阅读(1283)  评论(0编辑  收藏  举报