程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python JSON 操作 - JSON 與 Python 對象,自定義對象 之間的互相轉化

編輯: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類型

內容提要:

  1. json.dumps() 實踐
  2. json.loads() 實踐
  3. json.dump() 實踐
  4. json.loads() 實踐
  5. 如何動態設置 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 the cls kwarg; otherwise JSONEncoder 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 (a dict). The return value of object_hook will be used instead of the dict. 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
]
}
]
}

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved