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

使用Django ORM查询含JSON字段的表报TypeError如何解决

问题原因
  • 你之前用来更新JSON字段的脚本存在明显逻辑错误:第一行对jsonstring做反斜杠替换得到的new_clear,被第二行直接用原始jsonstring替换NaN的结果覆盖,反斜杠清理逻辑完全没有生效。
  • 不要全局删除JSON字符串中的所有反斜杠,会破坏JSON中合法的转义字符(比如转义引号、转义特殊字符),导致JSON格式损坏。
  • 报错本质是json.loads()方法接收到了dict类型的参数:大概率是你使用的PostgreSQL驱动(psycopg2)会自动将JSON/JSONB类型的字段值解析为Python dict,但Django的JSONField会默认对数据库返回的值再做一次反序列化,两次反序列化冲突导致报错;也有可能是部分记录存在双重序列化的问题(手动dumps后赋值给JSONField,导致JSONField又做了一次序列化)。
修复步骤

1. 临时获取目标记录的方法

如果你需要先快速拿到id=301的记录,可以用原生SQL强制将JSON字段转成字符串返回,避免自动解析冲突:

import json
from .models import House

# 只查询你需要的字段,result强制转text类型
test_object = House.objects.raw("SELECT id, result::text FROM house WHERE id = 301")[0]
# 手动反序列化result
result_data = json.loads(test_object.result)

2. 修复字段解析冲突

如果是psycopg2自动解析JSONB和Django JSONField反序列化逻辑冲突,在数据库配置中新增配置关闭psycopg2的自动解析即可:

# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': '你的库名',
        'USER': '你的用户名',
        'PASSWORD': '你的密码',
        'HOST': '你的地址',
        'PORT': '你的端口',
        'OPTIONS': {
            # 禁止psycopg2自动解析jsonb为dict
            'jsonb_loads': lambda s: s,
        },
    }
}

3. 批量修复已损坏的存量数据

import json
from django.db import connection, transaction
from .models import House

@transaction.atomic
def fix_json_data():
    with connection.cursor() as cursor:
        # 先获取所有记录的原始值
        cursor.execute("SELECT id, result FROM house")
        for obj_id, raw_result in cursor.fetchall():
            try:
                if isinstance(raw_result, str):
                    # 是字符串说明是未正确解析的JSON,转成dict后更新
                    parsed_val = json.loads(raw_result)
                    House.objects.filter(id=obj_id).update(result=parsed_val)
                elif isinstance(raw_result, dict):
                    # 已经是dict的直接更新,触发Django JSONField的正确序列化逻辑
                    House.objects.filter(id=obj_id).update(result=raw_result)
            except json.JSONDecodeError:
                print(f"记录ID {obj_id} 的JSON格式异常,需手动处理,原始值:{raw_result}")

# 执行修复
fix_json_data()

4. 修正之前的JSON格式化脚本

import json
from .models import House

data = House.objects.all() # 按需修改查询范围
for i in data:
    # 如果i.result本身是dict直接处理即可,不需要先dumps
    if isinstance(i.result, dict):
        # 处理NaN的问题,不需要全局删反斜杠
        jsonstring = json.dumps(i.result)
        new_clear = jsonstring.replace("NaN", "null")
        # 只处理双重转义的反斜杠,不要全删
        new_clear = new_clear.replace("\\\\", "\\")
        i.result = json.loads(new_clear)
    else:
        # 如果是字符串直接loads
        try:
            parsed = json.loads(i.result.replace("NaN", "null"))
            i.result = parsed
        except json.JSONDecodeError:
            print(f"记录ID {i.id} 格式错误跳过")
    i.save()

内容的提问来源于stack exchange,提问作者Alex Cortes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 03:06:04