Python JSON 操作 - JSON 与 Python 对象,自定义对象 之间的互相转化
前言
API 测试时,Request Body 和 Response Body 格式可能是JSON 格式,所以对 JSON 的处理显得非常重要。 关于 JSON 的概念请参考这篇《REST Assured 22 - JSON》
Python 对 JSON 的操作非常方便,主要有下面 4 个方法。
方法 | 功能 |
---|---|
json.dumps() | 将 Python 对象编码成 JSON 字符串 |
json.loads() | 将已编码的 JSON 字符串解码为 Python 对象 |
json.dump() | 将Python内置类型序列化为json对象后写入文件
|
json.load() |
读取文件 中json形式的字符串元素转化为Python类型 |
内容提要:
- json.dumps() 实践
- json.loads() 实践
- json.dump() 实践
- json.loads() 实践
- 如何动态设置 JSON request body
Python 对象编码成 JSON 字符串 json.dumps()
1. 字典 dict 转化成 JSON
import json
d = {"key1" : "value1", "key2" : "value2"}
json_string = json.dumps(d)
print("dic: {}".format(d))
print("json string: {}".format(json_string))
输出:
dict 中 key/value都是单引号
的,json 中的 key/value 是双引号
的。
dic: {'key1': 'value1', 'key2': 'value2'}
json string: {"key1": "value1", "key2": "value2"}
2. 格式化输出 JSON
控制缩进,key value 之间的连接符
import json
d = {"key1" : "value1", "key2" : "value2"}
json_string_pretty_1 = json.dumps(d, indent=2, separators=(',', ':'))
json_string_pretty_2 = json.dumps(d, indent=4, separators=(',', '='))
print("json string pretty 1 :\n {}".format(json_string_pretty_1))
print("json string pretty 2 :\n {}".format(json_string_pretty_2))
输出:两种不同的格式
json string pretty 1 :
{
"key1":"value1",
"key2":"value2"
}
json string pretty 2 :
{
"key1"="value1",
"key2"="value2"
}
3. 按 Key 排序输出 JSON 字符串sort_keys=True
按 key 排序
import json
d_dis_order = {"name" : "peter", "age": 18, "gender" : "men"}
json_in_order = json.dumps(d_no_order, indent=4, sort_keys=True)
print("dic disorder:\n {}".format(d_dis_order))
print("json string inorder:\n {}".format(json_in_order))
输出:
dic disorder:
{'name': 'peter', 'age': 18, 'gender': 'man'}
json string inorder:
{
"age": 18,
"gender": "man",
"name": "peter"
}
4. 将类对象转化成 JSON 字符串
自定义对象转化成 JSON 字符串,需要自定义一个 JSONEncoder
子类来覆盖默认的 系列化赋值给 cls 参数。
To use a custom
JSONEncoder
subclass (e.g. one that overrides the.default()
method to serialize additional types), specify it with thecls
kwarg; otherwiseJSONEncoder
is used.
import json
from json import JSONEncoder
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class PersonEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
peter = Person("Peter", 18, "Men")
json_peter = json.dumps(peter, indent=4, cls=PersonEncoder)
print("peter object:\n{}".format(peter))
print("json peter:\n{}".format(json_peter))
输出:
peter object:
<__main__.Person object at 0x000001FE156C9648>
json peter:
{
"name": "Peter",
"age": 18,
"gender": "Men"
}
JSON 字符串解码为 Python 对象 json.loads()
1. 访问 JSON 中的值
通过 json.loads() 方法将 JSON 字符串转化成 python 的 dict 对象就可以访问其键值了
import json
json_string = '''{"name":"peter", "age":18, "gender":"Men"}'''
data = json.loads(json_string)
print("json string:\n{}".format(json_string))
print("data:\n{}".format(data))
print("age: {}".format(data["age"]))
输出:
json string:
{"name":"peter", "age":18, "gender":"Men"}
data:
{'name': 'peter', 'age': 18, 'gender': 'Men'}
age: 18
2. 访问 JSON 嵌套对象
获取 JSON 字符串中 salary 的值
import json
json_string = '''
{
"company": {
"person": {
"name": "peter",
"age": 18,
"gender": "Men",
"pay": {
"salary": 3000,
"bonus": 5000
}
}
}
}
'''
data = json.loads(json_string)
print("json string:\n{}".format(json_string))
print("data:\n{}".format(data))
print("salary: {}".format(data["company"]["person"]["pay"]["salary"]))
输出:
通过 data[“company”][“person”][“pay”][“salary”] 访问到嵌套的值
json string:
{
"company": {
"person": {
"name": "peter",
"age": 18,
"gender": "Men",
"pay": {
"salary": 3000,
"bonus": 5000
}
}
}
}
data:
{'company': {'person': {'name': 'peter', 'age': 18, 'gender': 'Men', 'pay': {'salary': 3000, 'bonus': 5000}}}}
salary: 3000
3. 将 JSON 字符串转化成类对象object_hook
用于将 JSON 字符串解码成自定义的类对象, 默认object_hook= None 是解码成 dict. 所以要自定义一个解码方法。
object_hook
is an optional function that will be called with the result of any object literal decode (adict
). The return value ofobject_hook
will be used instead of thedict
. This feature can be used to implement custom decoders (e.g. JSON-RPC class hinting).
import json
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def PersonDecoder(obj):
return Person(obj['name'], obj['age'], obj['gender'])
person_json_string = '''{"name" : "peter", "age": 18, "gender" : "men"}'''
person_object = json.loads(person_json_string, object_hook=PersonDecoder)
print("person json string:\n{}".format(person_json_string))
print("peson object:\n{}".format(person_object))
print("name:{}\nage:{}\ngender:{}".format(person_object.name, person_object.age, person_object.gender))
输出:
person json string:
{"name" : "peter", "age": 18, "gender" : "men"}
peson object:
<__main__.Person object at 0x000001FFBCF4AA88>
name:peter
age:18
gender:men
4. 判断 JSON 格式是否正确
下面这个 JSON String 少了一个 ’ } '
json_string = '''
{
"company": {
"person": {
"name": "peter",
"age": 18,
"gender": "Men",
"pay": {
"salary": 3000,
"bonus": 5000
}
}
}
'''
def is_valid_JSON(json_data):
try:
json.loads(json_data)
except ValueError as err:
return False
return True
is_valid = is_valid_JSON(json_string)
print("json string is valid: {}".format(is_valid))
输出:
json string is valid: False
5. 获取 JSON 字符串中某个 key 所有的值
获取下面 JSON 字符串中所有 name 的 value
import json
json_string = '''
[
{
"id":1,
"name":"peter",
"hobby":[
"reading",
"movie"
]
},
{
"id":2,
"name":"lina",
"hobby":[
"sleep",
"shopping"
]
}
]
'''
json_data = json.loads(json_string)
name_list = [item.get("name") for item in json_data]
print(name_list)
输出:
['peter', 'lina']
将Python内置类型序列化为json对象后写入文件 json.dump()
1. 字典 dict 转化成 JSON 写入文件
import json
d = {"name" : "peter", "age": 18, "gender" : "men"}
with open("json.txt", 'w+') as f:
json.dump(d, f, indent=4)
json.txt 内容
2. 自定义类对象转化成 JSON 写入文本
需要自定义一个 JSONEncoder
子类来覆盖默认的 系列化赋值给 cls 参数。
import json
from json import JSONEncoder
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class PersonEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
person = Person("peter", 18, "men")
with open("json.txt", 'w+') as f:
json.dump(d, f, indent=4, cls=PersonEncoder)
json.txt 内容
读取文件
中 json 形式的字符串元素转化为Python类型 json.load()
1. 文本中 json 字符串转化成 dict
with open("json.txt", 'r') as f:
data = json.load(f)
print(data)
输出:
{'name': 'peter', 'age': 18, 'gender': 'men'}
2. 文本中的 json 字符串转化成自定义的类对象object_hook
用于将 JSON 字符串解码成自定义的类对象, 默认object_hook= None 是解码成 dict. 所以要自定义一个解码方法。
import json
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def PersonDecoder(obj):
return Person(obj['name'], obj['age'], obj['gender'])
with open("json.txt", 'r') as f:
person = json.load(f, object_hook=PersonDecoder)
print("name:{}\nage:{}\ngender:{}".format(person.name, person.age, person.gender))
如何动态设置 JSON request body
有时我们把 json 的 request 放在一个文本文件中,但并不是每次请求都用固定的 json body,需要动态地修改其中的值,最后还得转化成 json 字符串做为request body。
例如:json.txt 文本的内容
需要修改 collection-id 字段的值,将改动后的 json 字符串传入 request 作为 body
注意:json body key 都是双引号的,所以一定要将 python 的对象转化成 json 字符串,才能传入 request。
{
"search": {
"query": {
"collection-id": ["collection"]
}
},
"targets": [
{
"type": "subscription-id",
"value": [
1234
]
}
]
}
import json
with open("json.txt", 'r') as f:
data = json.load(f)
print("data:\n{}".format(data))
data["search"]["query"]["collection-id"] = ["collection_1", "collection_2", "collection_3"]
print("new data:\n{}".format(data))
json_data = json.dumps(data, indent=4)
print("json data:\n{}".format(json_data))
输出:
data:
{'search': {'query': {'collection-id': ['collection']}}, 'targets': [{'type': 'subscription-id', 'value': [1234]}]}
new data:
{'search': {'query': {'collection-id': ['collection_1', 'collection_2', 'collection_3']}}, 'targets': [{'type': 'subscription-id', 'value': [1234]}]}
json data:
{
"search": {
"query": {
"collection-id": [
"collection_1",
"collection_2",
"collection_3"
]
}
},
"targets": [
{
"type": "subscription-id",
"value": [
1234
]
}
]
}
推荐阅读
-
Python JSON 操作 - JSON 与 Python 对象,自定义对象 之间的互相转化
-
案例一:利于Python调用JSON对象来实现对XENA流量测试仪的灵活发包测试,能够适应Pair,Rotate,1-to-Many等多种拓扑模型
-
使用谷歌Gson实现Json数据与Java对象、List、Map之间的相互转换笔记
-
Python cookbook(数据结构与算法)从任意长度的可迭代对象中分解元素操作示例
-
FastJson对于JSON格式字符串、JSON对象及JavaBean之间的相互转换操作
-
详解Python中的__getitem__方法与slice对象的切片操作
-
把JSON数据格式转换为Python的类对象方法详解(两种方法)
-
详解Python中的__getitem__方法与slice对象的切片操作
-
解析JSON对象与字符串之间的相互转换
-
Python对象转换为json的方法步骤