You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将pandas DataFrame存为JSON并将首列账号设为JSON访问键

pandas DataFrame 转自定义嵌套JSON实现方案

原有方案问题原因

  • 导出JSON后用字符串替换索引的逻辑完全不可行:字符串替换会无差别匹配全文本中所有符合条件的内容,无法区分顶级键和字段值中出现的相同字符,必然导致数据错乱。
  • to_json默认只能导出扁平结构或固定层级结构,对于需要的多层嵌套(账户信息、交易历史、双卡嵌套信息)支持度很差,单元格中存储的字典会被序列化为字符串,无法生成合法的嵌套JSON结构。
  • 账号、卡号、手机号这类超长数字如果不提前转字符串类型,JSON序列化时会出现数字精度丢失,后几位自动变为0。

实现步骤

1. 读入数据并预处理索引

读入CSV后直接将账号列设为DataFrame索引,从根源上避免后续替换顶级键的操作,同时把所有长数字字段转为字符串规避精度问题。

import pandas as pd
import json
from datetime import datetime

# 读入源CSV文件,替换为你的实际文件路径
df = pd.read_csv("atm_source_data.csv")
# 长数字字段统一转字符串,避免精度丢失
long_num_cols = ["account_no", "uidai", "mobile_no", "pan", 
                 "debit_card_no", "debit_cvv", "credit_card_no", "credit_cvv"]
for col in long_num_cols:
    if col in df.columns:
        df[col] = df[col].astype(str)
# 将账号设为索引,导出时自动成为JSON顶级键
df = df.set_index("account_no")

注意:不要省略长数字转字符串的步骤,否则JSON解析时超过16位的数字会自动丢失精度,出现卡号、账号后几位变为0的问题。

2. 逐行组装嵌套字典结构

不要依赖to_json自动生成结构,逐行遍历DataFrame组装Python字典,灵活度最高,可以完全匹配目标JSON层级,同时初始化空的交易历史字段,方便后续ATM业务写入交易记录。

result = {}

for acc_no, row in df.iterrows():
    # 组装基础账户信息,字段名和目标JSON完全对齐
    account_info = {
        "account_no": acc_no,
        "account_type": row.get("account_type", "saving"),
        "branch": row.get("branch", ""),
        "branch_address": row.get("branch_address", ""),
        "ifsc": row.get("ifsc", ""),
        "uidai": row.get("uidai", ""),
        "mobile_no": row.get("mobile_no", ""),
        "email": row.get("email", ""),
        "fname": row.get("fname", ""),
        "mname": row.get("mname", ""),
        "sname": row.get("sname", ""),
        "acc_balance": float(row.get("acc_balance", 0)),
        "dob": row.get("dob", ""),
        "pan": row.get("pan", ""),
        "occupation": row.get("occupation", ""),
        "address": row.get("address", ""),
        "ac_open_date": row.get("ac_open_date", ""),
        "blood_group": row.get("blood_group", ""),
        # 初始化账户交易历史为空字典
        "history": {},
        "cards_allocated": {
            "credit": {},
            "debit": {}
        }
    }

    # 填充借记卡信息(如果CSV中有对应字段)
    if "debit_card_no" in df.columns and pd.notna(row["debit_card_no"]):
        account_info["cards_allocated"]["debit"] = {
            "debit_card_type": row.get("debit_card_type", "visa"),
            "debit_card_no": row["debit_card_no"],
            "name_on_card": f"{row['fname']} {row['mname']} {row['sname']}".lower(),
            "daily_debit_limit": float(row.get("daily_debit_limit", 20000)),
            "card_issue_date": row.get("debit_issue_date", ""),
            "card_exp_date": row.get("debit_exp_date", ""),
            "cvv": row.get("debit_cvv", ""),
            "debit_card_password": row.get("debit_password", ""),
            # 初始化借记卡交易历史
            "history": {}
        }

    # 填充信用卡信息(如果CSV中有对应字段)
    if "credit_card_no" in df.columns and pd.notna(row["credit_card_no"]):
        account_info["cards_allocated"]["credit"] = {
            "credit_card_type": row.get("credit_card_type", "platinum"),
            "credit_card_no": row["credit_card_no"],
            "name_on_card": f"{row['fname']} {row['mname']} {row['sname']}".lower(),
            "card_limit": float(row.get("credit_limit", 20000)),
            "amount_used": float(row.get("amount_used", 0)),
            "amount_to_pay": float(row.get("amount_to_pay", 0)),
            "card_issue_date": row.get("credit_issue_date", ""),
            "card_exp_date": row.get("credit_exp_date", ""),
            "cvv": row.get("credit_cvv", ""),
            "credit_card_password": row.get("credit_password", ""),
            "monthly_emi": float(row.get("monthly_emi", 0)),
            # 初始化信用卡交易历史
            "history": {}
        }

    result[acc_no] = account_info

3. 导出为JSON文件

组装完成的字典直接用标准库json模块导出即可,支持缩进格式化,编码正常不会出现乱码。

with open("atm_accounts.json", "w", encoding="utf-8") as f:
    json.dump(result, f, ensure_ascii=False, indent=4)

交易历史写入方法

后续开发ATM模拟器时,产生交易直接以dd_mm_yyyy_hh_mm_ss格式的时间戳为键,写入对应层级的history字段即可,不需要修改原始DataFrame:

# 示例:给指定账户加一条存款交易
time_key = datetime.now().strftime("%d_%m_%Y_%H_%M_%S")
result["12312312313"]["history"][time_key] = {
    "transition_id": "生成的全局唯一交易ID",
    "added": 5000,
    "withdrawn": 0
}
# 借记卡、信用卡交易同理,写入cards_allocated对应卡类型下的history字段即可

内容的提问来源于stack exchange,提问作者Shivam Gadekar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 05:21:47