目录
1 JSON是什么?
1.1 JSON是众多编程语言共同的“简谱”
JSON的全称是JavaScript Object Notation,中文翻译是JS对象简谱,是一种轻量级的数据交换格式。JavaScript是多用于Web前端开发的编程语言,支持面向对象的编程(OOP)。JSON从字面上看就是存储JS对象的一种简便、轻量的格式。
提到“简谱”,我们很容易想到音乐中的数字简谱,即使像我这种不懂音乐的人,也会觉得简谱看上去要比各种音符组成的五线谱更容易阅读一些。
JSON不仅能做JS对象的“简谱”, 还能做很多编程语言的“简谱”,而且是它们共同的“简谱”。不同的编程语言的语法是不一样的,因此不同语言编写的程序之间往往“语言不通”,比如:Java看不懂Python对象,Python也看不懂Java对象。为了不同的编程语言能够沟通,比较好的方法是把对象表达为一种简单易读的统一格式。
JSON用键值对的形式存储对象的属性名和属性值,每一个对象都放在一个大括号里。比如我用JSON给自己写一个对象,一个可爱型的女生,具有善良、聪明、开朗等个性,还养了一只2岁的泰迪犬,那么我的对象就有四个属性:性别、类型、个性和狗狗;狗狗也是一个对象,有品种和年龄两个属性。
{
"gender":"female",
"kind":"cute",
"character":["goodness"," intelligent","lively"],
"puppy":{
"breed":"teddy",
"age":2
}
}
当Java或者Python程序员就这点好,可以在程序的世界里随意写对象。好吧,言归正传,JSON表面上看是一个带有大括号、方括号和冒号的某种数据集合,但实际上是一个文本文件。这也是JSON实现跨平台、跨语言交换数据的重要基础。
1.2 JSON是一种高度结构化的文本
先想象一个场景,一个广东人跟一个上海人交流,他们互相听不懂对方的方言,但是两人把要说的内容用汉字写下来,立马就明白了对方的意思,这就是汉字的超方言性(笔者的专业是语言学)。
文本就具有类似于汉字的作用。不同的编程语言具有不同的数据结构类型体系,这就造成了互相沟通的障碍。但是所有的编程语言都会支持文本这一最基本的处理信息的类型。对于Python和Java来说,文本类型实际上就是字符串类型。
JSON中数据的组织方式是高度结构化的,结构化的第一个表现是层级性,上面写的那个对象中,对象里面嵌套着对象;在层级性的基础上,同一层级的数据要有对应性和有序性,键值对的格式保证了每一层数据间的对应关系;属性的值也有可能是存储多值的数据集合,其中的数据要排列有序。
我们可以在CSDN主页的XHR请求中观察JSON的层次结构,操作步骤以Google浏览器为例。
第一步:右键“检查” — 点击“Network” — 点击“XHR”;
第二步:重新加载页面 — 在左侧Name栏打开一个请求 — 点开右侧的preview — 观察层级结构
我们看到的那个能够一层层展开的结构,很像Python的字典或者Java的Map。但事实上,是XHR采用JSON格式传输数据。
2 如何在Python中使用JSON
2.1 内置库json的编码与解码
json是python的内置库,定义了 json.dumps(dict) 和 json.loads(json_str) 两个方法,前者用于将Python数据结构类型编码为json字符串,后者用于将json字符串解码为Python数据结构类型。
2.1.1 编码1:将字典编码为JSON字符串
我们在1.1中用json写好的那个“对象”与Python字典从外表上看一模一样,先将其写成字典(变量名spouse,就是配偶、对象的意思,哈哈哈),然后编码,方法的参数是Python字典:
import json
# 写一个 字典 类型的“对象”
spouse = {
"gender":"female",
"kind":"cute",
"character":["goodness"," intelligent","lively"],
"puppy":{
"breed":"teddy",
"age":2
}
}
# 将 字典 编码为 json字符串
spouse_json = json.dumps(spouse)
# 打印spouse和spouse_json
print(spouse)
print(spouse_json)
如果我们直接打印,会发现spouse和spouse_json在终端中显示出来的结果一模一样:
{'gender': 'female', 'kind': 'cute', 'character': ['goodness', ' intelligent', 'lively'], 'puppy': {'breed': 'teddy', 'age': 2}}
{"gender": "female", "kind": "cute", "character": ["goodness", " intelligent", "lively"], "puppy": {"breed": "teddy", "age": 2}}
如果我们分别打印二者的数据类型,会发现spouse是dict,spouse_json是str,对于Python来说,json就是一个高度结构化的字符串。
print(type(spouse)) # <class 'dict'>
print(type(spouse_json)) # <class 'str'>
2.1.2 编码2:将自定义类的对象编码为JSON字符串
将自定义类的对象转化为JSON字符串要经过一个中间步骤,即先将对象转化为字典,然后再将字典传入 json.dumps(dict) 方法。为了简化代码,自定义类就写三个属性作为演示。
import json
# 先自定义一个类
class Spouse:
def __init__(self, gender, kind, character):
self.gender = gender
self.kind = kind
self.character = character
# 类 实例化为一个 对象
spouse = Spouse("female","cute",['goodness', ' intelligent', 'lively'])
# 将 对象 转换为 字典
spouse_dict = spouse.__dict__
# 将 字典 传入 json.dumps(dict)方法
spouse_json = json.dumps(spouse_dict)
print(spouse_json)
print(type(spouse_json))
打印结果如下,成功将Python自定义对象转换为JSON字符串
{"gender": "female", "kind": "cute", "character": ["goodness", " intelligent", "lively"]}
<class 'str'>
2.1.3 解码1:将JSON字符串解码为字典
我们接着上面2.1.1的代码继续完成解码过程,将json_spouse传入json.loads()方法:
# 将 json字符串 解析为 字典
spouse_dict = json.loads(spouse_json)
print(spouse_dict)
print(type(spouse_dict))
打印效果如下,成功将JSON字符串解码为字典类型的数据
{'gender': 'female', 'kind': 'cute', 'character': ['goodness', ' intelligent', 'lively'], 'puppy': {'breed': 'teddy', 'age': 2}}
<class 'dict'>
2.1.4 解码2:将JSON字符串解码为自定义类的对象
和编码过程一样,解码也要经过一个中间步骤,先将JSON字符串转化为字典,再将字典转化成对象。我们接着2.1.2的代码完成解码过程。
# 将 json字符串 转化成 字典
spouse_dict = json.loads(spouse_json)
# 实例化一个对象,并将spouse_dict中的值传入
args = []
for v in spouse_dict.values():
args.append(v)
spouse2 = Spouse(args[0], args[1], args[2])
# 将 字典 转换成 对象
spouse2.__dict__ = spouse_dict
print(spouse2)
print(spouse2.gender, spouse2.kind, spouse2.character)
打印结果如下,成功将JSON转成自定义的Python对象,并取出三个属性的值
<__main__.Spouse object at 0x000002DB18BE1128>
female cute ['goodness', ' intelligent', 'lively']
2.2 requests库处理json的方法
requests库是一个第三方库,使用前需要安装,笔者习惯用清华镜像,速度比较快:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests
调用requests中的方法请求网页会返回一个response对象,再通过repsonse.json()的方法将其解码为Python字典。我们就拿1.2提到的CSDN主页中的一个XHR请求来演示。
还是1.2中得到XHR请求信息,然后按照下图的箭头点击Header,Request URL就是我们要用requests库请求的网址:
import requests
url = "https://silkroad.csdn.net/api/v2/assemble/list/channel/search_hot_word?channel_name=pc_hot_word&size=10&user_name=weixin_45370422&platform=pc&imei=10_36634027780-1586843824396-539212"
# 向url发起请求,返回一个response对象
res = requests.get(url)
# 将 respose对象 转换为 python字典
res_json = res.json()
print(res_json)
print(type(res_json))
打印结果如下,已经将在浏览器中看到的能层层展开的内容转换成python字典
{'code': 200, 'data': {'ext': {}, 'size': 10, 'items': [{'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': 'Google I/O 开发者大会', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-1.nonecase","hotword":"Google I/O 开发者大会"}', 'dist_request_id': '1622602100980_27895', 'index': '1', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-1.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-1.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 1, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': '领红包+快速涨粉!CSDN 测评赛开启', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-2.nonecase","hotword":"领红包+快速涨粉!CSDN 测评赛开启"}', 'dist_request_id': '1622602100980_27895', 'index': '2', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-2.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-2.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 2, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': 'CTO写低级Bug', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-3.nonecase","hotword":"CTO写低级Bug"}', 'dist_request_id': '1622602100980_27895', 'index': '3', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-3.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-3.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 3, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': '高质量自学网站', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-4.nonecase","hotword":"高质量自学网站"}', 'dist_request_id': '1622602100980_27895', 'index': '4', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-4.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-4.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 4, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': '为什么程序员不写文档?', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-5.nonecase","hotword":"为什么程序员不写文档?"}', 'dist_request_id': '1622602100980_27895', 'index': '5', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-5.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-5.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 5, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': 'C++编程入门', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-6.nonecase","hotword":"C++编程入门"}', 'dist_request_id': '1622602100980_27895', 'index': '6', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-6.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-6.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 6, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': 'python工程师', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-7.nonecase","hotword":"python工程师"}', 'dist_request_id': '1622602100980_27895', 'index': '7', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-7.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-7.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 7, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': 'python制作表情包', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-8.nonecase","hotword":"python制作表情包"}', 'dist_request_id': '1622602100980_27895', 'index': '8', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-8.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-8.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 8, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': '如何用Python追到女朋友', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-9.nonecase","hotword":"如何用Python追到女朋友"}', 'dist_request_id': '1622602100980_27895', 'index': '9', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-9.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-9.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 9, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': 'mysql', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-10.nonecase","hotword":"mysql"}', 'dist_request_id': '1622602100980_27895', 'index': '10', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-10.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-10.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 10, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}]}, 'message': 'success'}
<class 'dict'>
当然了,我们也可以迂回一下,先把response对象转换成字符串,然后调再json库的解码方法,效果是一样的:
import requests
import json
url = "https://silkroad.csdn.net/api/v2/assemble/list/channel/search_hot_word?channel_name=pc_hot_word&size=10&user_name=weixin_45370422&platform=pc&imei=10_36634027780-1586843824396-539212"
# 向url发起请求,返回一个response对象
res = requests.get(url)
# 将response对象转成字符串,再解码为python字典
res_json = json.loads(res.text)
print(res_json)
print(type(res_json))
打印结果是:
{'code': 200, 'data': {'ext': {}, 'size': 10, 'items': [{'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': 'Google I/O 开发者大会', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-1.nonecase","hotword":"Google I/O 开发者大会"}', 'dist_request_id': '1622602100980_27895', 'index': '1', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-1.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-1.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 1, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': '领红包+快速涨粉!CSDN 测评赛开启', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-2.nonecase","hotword":"领红包+快速涨粉!CSDN 测评赛开启"}', 'dist_request_id': '1622602100980_27895', 'index': '2', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-2.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-2.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 2, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': 'CTO写低级Bug', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-3.nonecase","hotword":"CTO写低级Bug"}', 'dist_request_id': '1622602100980_27895', 'index': '3', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-3.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-3.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 3, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': '高质量自学网站', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-4.nonecase","hotword":"高质量自学网站"}', 'dist_request_id': '1622602100980_27895', 'index': '4', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-4.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-4.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 4, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': '为什么程序员不写文档?', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-5.nonecase","hotword":"为什么程序员不写文档?"}', 'dist_request_id': '1622602100980_27895', 'index': '5', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-5.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-5.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 5, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': 'C++编程入门', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-6.nonecase","hotword":"C++编程入门"}', 'dist_request_id': '1622602100980_27895', 'index': '6', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-6.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-6.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 6, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': 'python工程师', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-7.nonecase","hotword":"python工程师"}', 'dist_request_id': '1622602100980_27895', 'index': '7', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-7.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-7.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 7, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': 'python制作表情包', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-8.nonecase","hotword":"python制作表情包"}', 'dist_request_id': '1622602100980_27895', 'index': '8', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-8.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-8.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 8, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': '如何用Python追到女朋友', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-9.nonecase","hotword":"如何用Python追到女朋友"}', 'dist_request_id': '1622602100980_27895', 'index': '9', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-9.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-9.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 9, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}, {'ext': None, 'resourceId': '', 'mediaAssetInfo': None, 'productId': 'mysql', 'reportData': {'eventClick': True, 'data': {'mod': 'popu_895', 'extra': '{"utm_medium":"distribute.pc_search_hot_word.none-task-hot_word-alirecmd-10.nonecase","hotword":"mysql"}', 'dist_request_id': '1622602100980_27895', 'index': '10', 'strategy': 'alirecmd'}, 'urlParams': {'utm_medium': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-10.nonecase', 'depth_1-utm_source': 'distribute.pc_search_hot_word.none-task-hot_word-alirecmd-10.nonecase'}, 'eventView': True}, 'recommendType': 'ali', 'index': 10, 'style': 'word_1', 'strategyId': 'alirecmd', 'productType': 'hot_word'}]}, 'message': 'success'}
<class 'dict'>
2.3 提取json中数据信息的方法
json中值得提取的信息一般就是对象的属性值。虽然json是一个文本,整体上是一个文本类型的数据,然而,这个文本通过特定的格式实现了高度的结构化,而且json中的数据类型与Python数据类型具有对应关系。如下表所示:
python数据类型 | json数据类型 | json格式示例 |
字典(dict) | 对象(object) | {属性名 : 属性值} |
列表(list)、元组(tuple) | 数组(array) | ·[元素1, 元素2, 元素3, ......] |
字符串(str) | 字符串(string) | '字符串' "字符串" |
整数(int)、浮点数(float) | 数字(number) | 666 |
布尔值(True, False) | 布尔值(true, false) | true false |
空值(None) | 空值(null) | null |
正因为有这样的对应关系,我们先将json字符串解码为Python字典后,就可以用处理Python数据类型的方法从里面提取数据信息了。比如我们上面写的json对象中的数据都能找到相应的Python数据类型。
3 如何在Java中使用JSON
3.1 Gson库和FastJson库的资源下载
Java目前没有像Python那样内置了处理JSON的类库,因此只能借助第三方库完成JSON的处理。这里推荐使用Google开发的Gson库和阿里开发的FastJson库,可以在各自的GitHub上下载,我们也将提供当前最新版本的资源供读者免费下载,链接在下面。
打包好的两个jar包资源:JSON-jar-new.zip-Java文档类资源-CSDN下载
Gson的GitHub地址:GitHub - google/gson: A Java serialization/deserialization library to convert Java Objects into JSON and back
FastJson的GitHub地址:Home · alibaba/fastjson Wiki · GitHub
至于导包的方法,网上很容易检索到,这里就不赘述了。这两篇博文还是讲的比较详细的:
IDEA:IDEA导入jar包_hwt1070359898的博客-CSDN博客_idea导入jar包
Eclipse:Eclipse引入jar包的三种方式_小蓝的博客-CSDN博客_eclipse 导入jar包
我们以1.1写的那个对象为例,首先创建一个“对象”类,即下面的Spouse.java,为了简化代码,节省篇幅,我们在全参构造方法里定义属性值。特别需要注意的一点是,阿里的FastJson是通过类的getter方法获取属性值的,所以必须要写上getter方法。
package com.demo2;
import java.util.Arrays;
public class Spouse {
// “对象”类的三个属性
private String gender;
private String kind;
private String[] character;
// Spouse类的全参构造方法的
public Spouse(String gender, String kind, String[] character) {
this.gender = gender;
this.kind = kind;
this.character = character;
}
// toString()方法:方便打印
@Override
public String toString() {
return "Spouse{" +
"gender='" + gender + '\'' +
", kind='" + kind + '\'' +
", character=" + Arrays.toString(character) +
'}';
}
// FastJson通过 getter 方法获取属性值
public String getGender() {
return gender;
}
public String getKind() {
return kind;
}
public String[] getCharacter() {
return character;
}
}
3.2 用Gson处理JSON的方法
3.2.1 编码1:将Map对象编码为JSON字符串
正如Python能够将字典类型的数据直接写入JSON,Java通过Map类型生成一个JSON。用Gson实现这一功能的方法是,先创建一个map对象,然后将其传入toJson(object)方法。
package com.demo2;
import com.google.gson.Gson;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) {
// 创建Map对象,加入键值对数据
Map map = new HashMap();
map.put("gender", "female");
map.put("kind", "cute");
map.put("character", new String[]{"goodness", " intelligent", "lively"});
// 将 map 传入 toJson(object) 方法
String json = new Gson().toJson(map);
System.out.println(json);
System.out.println(json.getClass());
}
}
打印的结果如下,成功生成一个JSON字符串:
{"character":["goodness"," intelligent","lively"],"gender":"female","kind":"cute"}
class java.lang.String
3.2.2 编码2:将自定义类的对象编码为JSON字符串
编码的方法是向toJson(object)方法传入自定义类的实例化对象。
import com.google.gson.Gson;
public class Demo {
public static void main(String[] args) {
// 1 创建 JSON 对象(如果只用一次,也可以写成匿名对象)
Gson gson = new Gson();
// 2 实例化Spouse类,得到一个对象
Spouse spouse = new Spouse("female", "cute", new String[]{"goodness", " intelligent", "lively"});
// 3 调用Gson的 toJson(object) 方法
String json = gson.toJson(spouse);
System.out.println(json);
System.out.println(json.getClass());
打印结果如下,可以看到对象被成功编码成了JSON格式的字符串
{"gender":"female","kind":"cute","character":["goodness"," intelligent","lively"]}
class java.lang.String
顺便提一下,如果所有的类都只用一次,那么上述代码可以进一步简化:
import com.google.gson.Gson;
public class Demo {
public static void main(String[] args) {
// 1 一行代码全部搞定
String json = new Gson().toJson(new Spouse("female", "cute", new String[]{"goodness", " intelligent", "lively"}));
3.2.3 解码1:将JSON字符串解码为Map对象
调用fromJson(json, class)方法,第一个参数为要解码的json字符串,第二个参数传入Map类。
package com.demo2;
import com.google.gson.Gson;
import java.util.List;
import java.util.Map;
public class Demo {
public static void main(String[] args) {
// 调用Gson对象的 fromJson(json, class) 方法 将json 解码为 Spouse对象
String json = "{\"gender\":\"female\",\"kind\":\"cute\",\"character\":[\"goodness\",\" intelligent\",\"lively\"]}";
// 可以将 JSON字符串 解码为 Map 对象,这样就能用Map的方法解析JSON
Map map = new Gson().fromJson(json, Map.class);
String gender = (String) map.get("gender");
System.out.println(gender);
// 可以将JSON中的数组解析为ArrayList
List character = (List) map.get("character");
System.out.println(character);
}
}
输出结果如下:
female
[goodness, intelligent, lively]
3.2.4 解码2:将JSON字符串解码为自定义类的对象
调用fromJson(json, class)方法,第一个参数为要解码的json字符串,第二个参数为要解码成的Java类。
package com.demo2;
import com.google.gson.Gson;
public class Demo {
public static void main(String[] args) {
// 调用Gson对象的 fromJson(json, class) 方法 将json 解码为 Spouse对象
String json = "{\"gender\":\"female\",\"kind\":\"cute\",\"character\":[\"goodness\",\" intelligent\",\"lively\"]}";
Spouse spouse = new Gson().fromJson(json, Spouse.class);
System.out.println(spouse);
}
}
输出结果如下,成功调用了Spouse类的toString()方法,打印出各属性的值:
Spouse{gender='female', kind='cute', character=[goodness, intelligent, lively]}
3.3 用FastJson处理JSON的方法
3.3.1 编码1:将Map对象编码为JSON字符串
提供有两种生成JSON的方法,第一种类似于3.2.3的方法,先创建map对象,然后将map作为参数传入JSON.toJsonString(object)方法。
第二种方法是实例化FastJson提供的JSONObject类,用这个类的对象生成JSON。这个类能够调用Map类的方法,其原因是它实现了Map接口,观察这段源码:
代码示例如下:
package com.demo2;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) {
/**
* 方法一:实例化一个map对象
*/
Map map = new HashMap();
map.put("gender", "female");
map.put("kind", "cute");
map.put("character", new String[]{"goodness", " intelligent", "lively"});
// 将 map对象 传入 JSON.toJsonString(object) 方法
String json = JSON.toJSONString(map);
System.out.println(json);
System.out.println(json.getClass());
System.out.println();
/**
* 方法二:实例化一个JSONObjcet的对象,
*/
JSONObject jsonObject = new JSONObject();
// 调用 put(key, value) 方法
jsonObject.put("gender", "female");
jsonObject.put("kind", "cute");
jsonObject.put("character", new String[]{"goodness", " intelligent", "lively"});
System.out.println(jsonObject);
System.out.println(jsonObject.getClass());
}
}
打印结果如下:
{"character":["goodness"," intelligent","lively"],"gender":"female","kind":"cute"}
class java.lang.String
{"character":["goodness"," intelligent","lively"],"gender":"female","kind":"cute"}
class com.alibaba.fastjson.JSONObject
两种方法相比,方法二略微简便一点。另外我们也看到,第二种方法返回的数据类型是FastJson自己定义的JSONObject。
3.3.2 编码2:将自定义类的对象编码为JSON字符串
将自定义类的对象传入JSON.toJsonString(object)方法,就得到了对象的JSON字符串。
package com.demo2;
import com.alibaba.fastjson.JSON;
import java.util.List;
public class Demo {
public static void main(String[] args) {
Book book = new Book("1002","唐诗","床前");
Spouse spouse = new Spouse("female", "cute", new String[]{"goodness", "intelligent", "lively"});
// 将 对象 编码 为JSON字符串
String json = JSON.toJSONString(spouse);
System.out.println(json);
System.out.println(json.getClass());
打印结果如下
{"character":["goodness","intelligent","lively"],"gender":"female","kind":"cute"}
class java.lang.String
3.3.3 解码1:将JSON字符串解码为Map对象
方法是将JSON字符串传入JSON.parseObject(json, class)方法的一个参数,第二个参数是Map类。
package com.demo2;
import com.alibaba.fastjson.JSON;
import java.util.Map;
public class Demo7 {
public static void main(String[] args) {
// 解码为 HashMap
String json = "{\"character\":[\"goodness\",\" intelligent\",\"lively\"],\"gender\":\"female\",\"kind\":\"cute\"}";
Map map = JSON.parseObject(json, Map.class);
System.out.println(map);
System.out.println(map.getClass());
}
}
打印结果如下:
{character=["goodness"," intelligent","lively"], gender=female, kind=cute}
class java.util.HashMap
3.3.4 解码2:将JSON字符串解码为自定义类的对象
介绍两种解码的方法:JSON.parseObject(json, class) 和 JSON.parseArray(json, class) ,分别解析JSON对象和JSON里面的数组,第一个参数是JSON字符串,第二个参数是要解析成哪个类。
package com.demo2;
import com.alibaba.fastjson.JSON;
import java.util.List;
public class Demo4 {
public static void main(String[] args) {
// 将 json字符串 解码为 对象,{"character":["goodness","intelligent","lively"],"gender":"female","kind":"cute"}
String json = "{\"character\":[\"goodness\",\"intelligent\",\"lively\"],\"gender\":\"female\",\"kind\":\"cute\"}";
Spouse spouse = JSON.parseObject(json,Spouse.class);
System.out.println(spouse);
System.out.println(spouse.getClass());
// 解析 json字符串 的数组,解析为ArrayList
List<String> stringList = JSON.parseArray("[\"goodness\",\"intelligent\",\"lively\"]", String.class);
System.out.println(stringList);
System.out.println(stringList.getClass());
}
}
打印结果如下,注意观察解码后的数据类型:
Spouse{gender='female', kind='cute', character=[goodness, intelligent, lively]}
class com.demo2.Spouse
[goodness, intelligent, lively]
class java.util.ArrayList