最近碰到这么一个业务问题,是需要解析一段接送json数据,众所周知json为dict Key-Value 并且json数据含有多个键值对 如何只提取想要的key所对应的value呢 直接上代码
先来展示一段json代码
{
"d": {
"results": [
{
"__metadata": {
"uri": "https://baidu.com')",
"type": "EmpEmploymentTermination"
},
"userId": "101118",
"customString17": null,
"customString87": "39443",
"lastDateWorked": "\/Date(1651276800000)\/"
},
{
"__metadata": {
"uri": "https://baidu.com')",
"type": "EmpEmploymentTermination"
},
"userId": "102974",
"customString17": null,
"customString87": null,
"lastDateWorked": "\/Date(1660003200000)\/"
},
{
"__metadata": {
"uri": "https://baidu.com')",
"type": "EmpEmploymentTermination"
},
"userId": "102917",
"customString17": null,
"customString87": null,
"lastDateWorked": "\/Date(1651190400000)\/"
}
]
}
}
这个是一个比较规律一点的json数据,现在要取这个里面的userId、customString17、customString87、和lastDateWorked这些key以及value,然后存入到Excel中去
因为json数据会有很多层,所以我这里使用的最好的方法是迭代,让程序自己进行判断一层一层往下进行判断,最后取出我们想要的东西
先将以上json保存成json文件
# 导入所需要的库
import json
class ExtractJson():
def __init__(self):
self.data = None
def loadJsonData(self):
# 加载json
file = r'./data/test_json.json'
with open(file, 'r', encoding='utf-8') as data:
jsonData = json.load(data)
print(jsonData)
return jsonData
def extractJsonData(self):
# 使用列表模拟我们所需要的key
needKeys = ['userId', 'customString17', 'customString87', 'lastDateWorked']
# 调用loadJsonData返回json
jsonData = ExtractJson().loadJsonData()
# 写迭代函数直接处理jsonData
def checkKeyValue(jsonData, key, valueLis):
# 使用内置函数isinstance进行判断是否为某类型
if isinstance(jsonData, list):
for i in jsonData:
if key in str(i):
checkKeyValue(i, key, valueLis)
elif isinstance(jsonData, dict):
if jsonData.get(key) != None:
valueLis.append(jsonData[key])
else:
for k, v in jsonData.items():
if key in str(v):
checkKeyValue(v, key, valueLis)
else:
try:
# 需要注意的是使用的json.loads这个是将文本转换为json所使用的
# 加载我们使用的是json.load
checkKeyValue(json.loads(jsonData), key, valueLis)
except:
return
# 传入jsondata
# 循环读取needKeys 并且使用checkKeyValue获取数据
dataAll = []
# 预防有时数据转换为字典类型而出错,添加json.dumps()将dict类型转换为json类型
# 使用转义'\',添加双引号
jsonData = json.dumps(jsonData).replace("null", '\"replaceValue\"')
for k in needKeys:
valueLis = []
# checkKeyValue直接返回的是一个List
checkKeyValue(json.loads(jsonData), k, valueLis)
dataAll.append(valueLis)
print(dataAll)
return dataAll, needKeys
if __name__ == '__main__':
ss = ExtractJson()
ss.extractJsonData()
这个是运行结果 可以看到有一个为空,而且数据的数量是对照不上的,可是为了保证数据的完整性为空的直接放成空值 所以一个方法就是直接在jsondata里面直接将空值替换成任意一个字段,但是要保证不与需要提取的key重复,方便数据准确性和后续修改
替换json数据空值为任意字段
需要注意的是json需要为双引号数据,不然会出错
# 替换数据代码
jsonData = json.dumps(jsonData).replace("null", '\"replaceValue\"')
def listToDataframe(self):
dataAll, cols = ExtractJson().extractJsonData()
print('未处理之前:', dataAll)
# 因为是一个整体 我们需要打包并且进行处理
dataAll = zip(*dataAll)
dataAll2 = [list(i) for i in dataAll]
print('处理之后:', dataAll2)
变成直接可以转换为dataframe的嵌套列表
完整代码,直接转换为dataframe格式
顺便说一句将数据里面的[lastDateWorked]转换为datetime格式
因为是毫秒所以需要转换一下,使用的是time函数的localtime函数
# 导入所需要的库
import json
import time
import pandas as pd
class ExtractJson():
def __init__(self):
self.data = None
def loadJsonData(self):
# 加载json
file = r'./data/test_json.json'
with open(file, 'r', encoding='utf-8') as data:
jsonData = json.load(data)
return jsonData
def extractJsonData(self):
# 使用列表模拟我们所需要的key
needKeys = ['userId', 'customString17', 'customString87', 'lastDateWorked']
# 调用loadJsonData返回json
jsonData = ExtractJson().loadJsonData()
# 写迭代函数直接处理jsonData
def checkKeyValue(jsonData, key, valueLis):
# 使用内置函数isinstance进行判断是否为某类型
if isinstance(jsonData, list):
for i in jsonData:
if key in str(i):
checkKeyValue(i, key, valueLis)
elif isinstance(jsonData, dict):
if jsonData.get(key) != None:
valueLis.append(jsonData[key])
else:
for k, v in jsonData.items():
if key in str(v):
checkKeyValue(v, key, valueLis)
else:
try:
# 需要注意的是使用的json.loads这个是将文本转换为json所使用的
# 加载我们使用的是json.load
checkKeyValue(json.loads(jsonData), key, valueLis)
except:
return
# 传入jsondata
# 循环读取needKeys 并且使用checkKeyValue获取数据
dataAll = []
jsonData = json.dumps(jsonData).replace("null", '\"replaceValue\"')
for k in needKeys:
valueLis = []
# checkKeyValue直接返回的是一个List
checkKeyValue(json.loads(jsonData), k, valueLis)
dataAll.append(valueLis)
return dataAll, needKeys
def listToDataframe(self):
dataAll, cols = ExtractJson().extractJsonData()
# 因为是一个整体 我们需要打包并且进行处理
dataAll = zip(*dataAll)
dataAll2 = [list(i) for i in dataAll]
df = pd.DataFrame(dataAll2, columns=cols)
# 切记把里面的replaceValues替换为空值
df = df.replace('replaceValue',None)
# 顺便说一个将lastDateWorked转换为datetime格式
# 因为是毫秒所以需要转换一下,使用的是time函数的localtime函数
def change_date(x):
if x != None:
# 先把括号里面的秒拿出来
seconds = int(x.split('(')[1].split(')')[0])
time_ = time.strftime('%Y-%m-%d', time.localtime(seconds/1000))
return time_
# 使用apply函数完成转换
df['lastDateWorked'] = df['lastDateWorked'].apply(change_date)
print(df)
# 输出到excel中去
df.to_excel('jsonFinish.xlsx', index=False)
if __name__ == '__main__':
ss = ExtractJson()
ss.listToDataframe()
如何上传df到数据库 请参考我之前的文章python自动创建sqlserver表并上传dataframe到创建的表中
如有其他更好的做法 欢迎探讨 谢谢!!!!想要测试数据可以私信我