本文内容为原创,转载请说明出处
文章目录
一、json解析失败报错:json.decoder.JSONDecodeError
最近遇到一个将JSON文件转CSV的问题,尝试python直接使用json.loads由字符串转字典失败,在csdn上没有找到相应解答,我将分享处理该问题的思路方法及代码,仅供参考,有错误请批评指正。json文件格式如下:
{
"key1" : "value1",
"key2" : "value2",
"key3" : "value3",
"key4" : {
"key5" : "value4",
"key6" : "value5"
},
"key7" : "value6",
"key8" : "value7"
}
{
"key1" : "value8",
"key2" : "value9",
"key3" : "value10",
"key4" : {
"key5" : "value11",
"key6" : "value12"
},
"key7" : "value13",
"key8" : "value14"
}
解码失败原因:该json文件格式特点在于文件内有多个“字典”组成(这里的“字典”只是由于json文件存储格式形似字典所以简称,实则不严谨,后续正文带引号的字典则表示json文件该形式的内容),并且“字典”与“字典”之间没有逗号分隔符,而json.loads是把一整个json文件作为一个字符串转换为字典,各“字典”无法分割开,因此解码失败报错。
二、解决思路:先转化成常见的json格式
首先,需要在各“字典”之间加入逗号进行分隔,代码如下,可直接使用:
'''加逗号分隔符,并且使json文件变为列表形式'''
def add_delimiter(input_data, real_input):
'''
:param input_data: 原始输入json文件
:param new_input: 加完分隔符的实际输入json文件
:return: 无
'''
with open(input_data, 'r', encoding="utf-8") as fr:
with open(real_input, 'w', encoding="utf-8") as fw:
for line in fr: #读取input_data中每一行
if line == "}\n": #观察结构可得,判断行内容为"}"以及换行符"\n"时
fw.writelines(line.strip("\n") + ',' + "\n") #变为"},"
else: #其余不变
fw.writelines(line)
with open(real_input, 'r+', encoding="utf-8") as fs:
content = fs.read() #读取real_input中的所有内容
fs.seek(0) #指针指到文件开头
fs.write("[")
fs.write(content)
fs.seek(0,2) #指针指到末尾,偏移量为0
fs.write("]")
print("加完分隔符的json文件已写入完毕!")
input_data = "input_data.json"
real_input = "real_input.json"
add_delimiter(input_data, real_input)
此时,得到了每个“字典”之间都有逗号作为分隔符的实际输入文件,在文件头尾分别加入"[“和”]"使其变成列表形式,方便后续遍历拿到每一个“字典”。
三、临床疾病问诊的实际问题
任务要求:所取标签以及内容
我们所需要的五个标签分别是disease_name、disease_subject、question、treatment、symptom,需要将标签以及对应内容从json文件中提取,并写入新的csv文件。以下是部分原文件即input_data:
{
"disease_name" : "A链球菌群感染(别名:化脓性链球菌感染,酿脓链球菌感染)",
"disease_url" : "https://m.120ask.com/jibing/alqjqgr/",
"disease_subject" : "呼吸内科",
"ask_dict" : {
"question" : "青霉素最多连续输几天呢",
"question_href" : "http://m.120ask.com/jibing/alqjqgr/1228786.html"
},
"treatment" : "A链球菌群感染治疗治疗药物首选青霉素,但应考虑到可能有耐药菌株,应加大剂量或改用他药,如红霉素,克林霉素,第一代、二代头孢类抗生素等。最好参照当地药敏结果选用。由于A组链球菌感染与风湿热的密切关系,风湿性心脏病或风湿热患者宜预防应用抗菌药防止链球菌呼吸系感染的发生青霉素为首选预防用药,可应用苄星青霉素,成人每月肌内注射120万U小儿60万~120万U疗程数年以上,直至病情稳定为止。对青霉素过敏者可予红霉素250mg每天2次长期服用如患者不能坚持长疗程者可定期作咽拭培养,发现A组链球菌时则按急性链球菌咽炎予青霉素或红霉素治疗一疗程剂量同前述。对猩红热患者应予以隔离治疗以控制传染源隔离期6天,咽拭培养转阴无并发证者即可出院,亦可家庭隔离幼托机构或学校发生猩红热流行时,对急性咽炎和扁桃体炎者均应按猩红热隔离治疗,对易感人群中密切接触者检疫7~12天,也有主张给予青霉素预防用药者。对带菌者亦应予青霉素治疗直至培养转阴,以控制传染源,此对幼托机构的工作人员尤为重要。",
"symptom" : "A链球菌群感染症状A链球菌群可引起全身各处的化脓性疾病,最常见的有以下几种。1.急性咽喉炎、急性扁桃体炎患者以儿童为多。多发生于冬春季节。患者可有发热、咽痛、头痛等症状。检查可见咽部及扁桃体充血、水肿以及脓性渗出物,可形成伪膜。恢复期部分患者可出现风湿病或肾炎。2.丹毒皮肤有微小损伤(如足癣)或发生退化时(老年)易引起丹毒的发生。细菌进入破损处后可经淋巴扩散。患者可有发热、头痛、全身不适等全身性症状。数小时内局部皮肤出现红斑,边界清楚,且高出正常皮肤。严重者可出现含有脓性液体的大疱和组织坏死,附近淋巴结可肿大且有压痛。3.皮肤及软组织感染新生儿脐部感染;婴幼儿可患脓疱病;手术伤口感染等。蜂窝织炎常可导致菌血症。最严重的为坏死性筋膜炎,为皮下深部筋膜及脂肪进行性坏死性感染过程。感染多起始于创伤(不显眼的外伤)或手术。局部出现红、肿、热、痛,很快向外扩展,24~48小时病变处颜色由红变紫,继而变蓝,形成含有黄色液体的水疱和大疱。在第4~5天时紫色区开始坏死,7~10天时边界清楚,坏死的皮肤脱落,显露出皮下广泛的坏死组织。患者发高热、衰弱、反应迟钝,极易引起菌血症、败血症,实际上TSLS患者多伴有严重的软组织感染。尚有患者可患肌炎,但多与坏死性筋膜炎并存,单发者少见。4.中毒性休克样综合征(TSS)从20世纪80年代后期,本已少见的严重A群菌感染又明显增多。患者多为20~50岁身体健康者。病原菌多为A组菌M1和M3型,还有M12和M28型,均能产生外毒素A和B。入侵门户多为皮肤和软组织,特别重要的是蜂窝织炎和坏死性筋膜炎(可占70%)。肺部感染亦为重要来源。患者发冷、高热,伴有某部位剧烈疼痛,如肢体、胸部、心脏(可似心肌梗死)、关节、腹部(像腹膜炎样)等处。均有低血压乃至休克,嗜睡,意识模糊甚至精神错乱,出现幻觉等;肾功能受损甚至急性肾衰竭;肝功能可异常,ALT及血胆红素可增高;还可出现急性呼吸窘迫综合征。不少患者血清蛋白减低、血钙血钠减少等。5.其他感染A链球菌群可引起内眼炎、鼻窦炎、阴道炎、子宫内膜炎、肺炎等。机体免疫力不足者可发展成菌血症,进而出现脑膜炎、心内膜炎、腹膜炎、关节炎、骨髓炎、产褥热、血栓性静脉炎等。"
}
{
"disease_name" : "Austin型幼儿脑硫脂病(别名:Austin型异染性脑白质营养不良)",
"disease_url" : "https://m.120ask.com/jibing/austinxyenlzb/",
"disease_subject" : "神经内科",
"ask_dict" : {
"question" : "Austin型幼儿脑硫脂病容易与哪些疾病混淆?",
"question_href" : "http://m.120ask.com/jibing/austinxyenlzb/24970.html"
},
"treatment" : "Austin型幼儿脑硫脂病治疗本病无特效方法治疗,关键在于预防。基因治疗、干细胞治疗等可延缓疾病的发生和发展。",
"symptom" : "Austin型幼儿脑硫脂病症状本病患儿从9个月到24个月出现临床症状。早期临床表现为行为异常、烦躁不安、共济失调、动作不协调、步态异常,多数患儿可出现肌张力低下,偶尔出现痉挛性截瘫。病情持续一年以后,患儿不能站立,反应迟钝也更加明显。可表现为语言障碍、肌张力增高(下肢更为明显)、深反射减弱或缺如、共济失调加重,可出现间歇性肢体疼痛等。3~4岁时,患儿卧床不起,出现四肢瘫,并发生眼球震颤、小脑病变体征。抽搐、视神经萎缩及反应迟钝进一步加重。眼底检查可见黄斑呈灰色,以后可能失明。除神经系统症状外,还可因多发性骨发育不良引起骨骼畸形,面容呈轻度Hurler综合征特征等。"
}
提取各标签及内容并转为csv文件保存
import json
import pandas as pd
from pandas import DataFrame
'''json文件转换为csv文件'''
def to_csv(real_input, csv_file):
'''
:param real_input: 加完分隔符的实际输入json文件
:param csv_file: 转换后的csv文件
:return: 无
'''
data = { #每一个需要的标签作为key,空列表作为值存入新定义的data字典
'disease_name': [],
'disease_subject': [],
'question': [],
'treatment': [],
'symptom': []
}
with open(real_input, "r", encoding="utf-8") as fr:
dicts = json.load(fr) # 注意这里一定是用json.load拿到每一个字典而不是json.loads
for dict in dicts: # 遍历每一个字典dict
data['disease_name'].append(dict['disease_name'])
data['disease_subject'].append(dict['disease_subject'])
data['question'].append(dict["ask_dict"]["question"]) #嵌套字典索引
data['treatment'].append(dict["treatment"])
data['symptom'].append(dict["symptom"])
output=DataFrame(data, columns=["disease_name","disease_subject","question","treatment","symptom"])
output.to_csv(csv_file, header=True, index=False) #用pandas写入csv
real_input = "real_input.json"
csv_file = "csv_file.csv"
to_csv(real_input, csv_file)
CSV文件格式的最终结果
完整代码
import json
import pandas as pd
from pandas import DataFrame
'''加逗号分隔符,并且使json文件变为列表形式'''
def add_delimiter(input_data, real_input):
'''
:param input_data: 原始输入json文件
:param new_input: 加完分隔符的实际输入json文件
:return: 无
'''
with open(input_data, 'r', encoding="utf-8") as fr:
with open(real_input, 'w', encoding="utf-8") as fw:
for line in fr: #读取input_data中每一行
if line == "}\n": #观察结构可得,判断行内容为"}"以及换行符"\n"时
fw.writelines(line.strip("\n") + ',' + "\n") #变为"},"
else: #其余不变
fw.writelines(line)
with open(real_input, 'r+', encoding="utf-8") as fs:
content = fs.read() #读取real_input中的所有内容
fs.seek(0) #指针指到文件开头
fs.write("[")
fs.write(content)
fs.seek(0,2) #指针指到末尾,偏移量为0
fs.write("]")
print("加完分隔符的json文件已写入完毕!")
input_data = "input_data.json"
real_input = "real_input.json"
add_delimiter(input_data, real_input)
'''json文件转换为csv文件'''
def to_csv(real_input, csv_file):
'''
:param real_input: 加完分隔符的实际输入json文件
:param csv_file: 转换后的csv文件
:return: 无
'''
data = { #每一个需要的标签作为key,空列表作为值存入新定义的data字典
'disease_name': [],
'disease_subject': [],
'question': [],
'treatment': [],
'symptom': []
}
with open(real_input, "r", encoding="utf-8") as fr:
dicts = json.load(fr) # 注意这里一定是用json.load拿到每一个字典而不是json.loads
for dict in dicts: # 遍历每一个字典dict
data['disease_name'].append(dict['disease_name'])
data['disease_subject'].append(dict['disease_subject'])
data['question'].append(dict["ask_dict"]["question"]) #嵌套字典索引
data['treatment'].append(dict["treatment"])
data['symptom'].append(dict["symptom"])
output=DataFrame(data, columns=["disease_name","disease_subject","question","treatment","symptom"])
output.to_csv(csv_file, header=True, index=False) #用pandas写入csv
csv_file = "csv_file.csv"
to_csv(real_input, csv_file)
END