API 測試時,Request Body 和 Response Body 格式可能是JSON 格式,所以對 JSON 的處理顯得非常重要。 關於 JSON 的概念請參考這篇《REST Assured 22 - JSON》
Python 對 JSON 的操作非常方便,主要有下面 4 個方法。
寫入文件
json.load()讀取文件
中json形式的字符串元素轉化為Python類型內容提要:
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.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']
寫入文件 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 放在一個文本文件中,但並不是每次請求都用固定的 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
]
}
]
}