Python读取含多个字典的JSON并加载为DataFrame的方法
读取失败原因
两类文件都不符合标准JSON规范,常规json库、pandas.read_json接口无法直接识别:
- 第一类文件每行是Python字典格式,使用单引号包裹键和字符串值,而标准JSON要求字符串必须用双引号包裹
- 第二类文件是多个独立JSON数组直接首尾拼接,数组间无分隔符、无外层包裹结构,不符合标准JSON的结构要求
第一类文件(逐行字典格式)读取方案
使用ast.literal_eval逐行解析即可,该方法可以安全解析Python原生字面量(字典、列表等),不存在代码注入风险。
完整示例代码:
import ast import pandas as pd records = [] # 替换为你的实际文件路径 with open("dict_format_file.txt", "r", encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue # 解析当前行的字典结构 record = ast.literal_eval(line) records.append(record) # 直接转成DataFrame,此时b、a列存储的是二维数组 df = pd.DataFrame(records)
如果需要把b(买盘)、a(卖盘)的二维数组拆分成明细行,可以追加以下处理代码:
# 分别展开买盘、卖盘列,添加交易类型标记 df_bid = df.explode("b")[["E", "s", "b"]].rename(columns={"b": "value_pair"}) df_bid["trade_type"] = "bid" df_ask = df.explode("a")[["E", "s", "a"]].rename(columns={"a": "value_pair"}) df_ask["trade_type"] = "ask" # 合并后拆分价格、成交量字段,做类型转换 df_detail = pd.concat([df_bid, df_ask]).reset_index(drop=True) df_detail[["price", "volume"]] = pd.DataFrame(df_detail["value_pair"].tolist(), index=df_detail.index) df_detail = df_detail.drop(columns=["value_pair"]) df_detail["price"] = df_detail["price"].astype(float) df_detail["volume"] = df_detail["volume"].astype(float) # 时间戳转datetime,原字段E是毫秒级时间戳 df_detail["trade_time"] = pd.to_datetime(df_detail["E"], unit="ms")
第二类文件(连续二维数组格式)读取方案
使用json.JSONDecoder的raw_decode方法循环解析即可,该方法可以从指定位置开始解析合法JSON片段,返回解析结果和结束位置,刚好适配连续拼接的JSON结构。
完整示例代码:
import json import pandas as pd decoder = json.JSONDecoder() all_rows = [] with open("array_format_file.txt", "r", encoding="utf-8") as f: content = f.read().strip() pos = 0 while pos < len(content): # 从当前位置解析一个二维数组 current_array, pos = decoder.raw_decode(content, pos) # 跳过数组之间的空白字符 while pos < len(content) and content[pos].isspace(): pos += 1 # 把当前数组的所有价格成交量对加入总列表 all_rows.extend(current_array) # 转成DataFrame,根据业务含义命名字段即可 df = pd.DataFrame(all_rows, columns=["price", "volume"]) # 转换数值类型 df["price"] = df["price"].astype(float) df["volume"] = df["volume"].astype(float)
注意:禁止直接使用
eval()解析文件内容,如果文件被恶意篡改,eval()会执行任意恶意代码,上述用到的ast.literal_eval和json.JSONDecoder.raw_decode均为安全解析方法,不存在该风险。
内容的提问来源于stack exchange,提问作者Thelvguy
相关产品推荐
相关产品推荐

