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

在Django中存储含float.inf的元组列表至PostgreSQL JSONB字段

解决包含Infinity的元组列表存入PostgreSQL JSONB字段的问题

你遇到的问题核心在于JSON标准本身不支持Infinity和NaN,Python默认的JSONEncoder会把float.inf序列化为字符串"Infinity",但PostgreSQL的jsonb类型不识别这个标记,因此抛出了语法错误。下面是一套简单可行的序列化/反序列化方案:

1. 自定义JSON编码器处理特殊值

我们需要继承JSON编码器,把inf、-inf、NaN转换成JSON兼容的字符串标记,同时把元组转为列表(因为JSON没有元组类型):

import json
from django.core.serializers.json import DjangoJSONEncoder

# 继承Django默认编码器,保留对datetime等Django常用类型的支持
class MathJSONEncoder(DjangoJSONEncoder):
    def default(self, obj):
        # 处理浮点特殊值
        if isinstance(obj, float):
            if obj == float('inf'):
                return "inf"
            elif obj == float('-inf'):
                return "-inf"
            elif obj != obj:  # 判断是否为NaN
                return "nan"
        # 把元组转为列表(JSON仅支持数组)
        elif isinstance(obj, tuple):
            return list(obj)
        # 其他类型交给父类处理
        return super().default(obj)

2. 在Django模型中指定编码器

直接在JSONField里配置我们自定义的编码器,这样保存数据时会自动处理:

from django.db import models

class YourModel(models.Model):
    a_math_function = models.JSONField(encoder=MathJSONEncoder)
    # 其他字段...

现在你可以正常保存包含float.inf的元组列表了:

data = [(float.inf, 1.0), (270, 0.9002), (0, 0.0)]
YourModel.objects.create(a_math_function=data)

此时存入数据库的JSON数据会是:[["inf", 1.0], [270, 0.9002], [0, 0.0]],完全符合PostgreSQL jsonb的语法要求。

3. 反序列化还原原始数据

从数据库取出数据时,需要把字符串标记转回对应的浮点特殊值,同时把列表还原为元组。我们可以写一个自定义解码器:

def math_json_decoder(obj):
    # 处理数组(原元组转成的列表)
    if isinstance(obj, list):
        processed_items = []
        for item in obj:
            # 递归处理嵌套元素
            processed = math_json_decoder(item)
            # 如果是嵌套列表(原元组),转回元组
            if isinstance(item, list) and len(item) == 2:  # 根据你的元组结构调整
                processed_items.append(tuple(processed))
            else:
                processed_items.append(processed)
        return processed_items
    # 处理字符串标记,转回特殊浮点值
    elif isinstance(obj, str):
        if obj == "inf":
            return float('inf')
        elif obj == "-inf":
            return float('-inf')
        elif obj == "nan":
            return float('nan')
        else:
            return obj
    # 其他类型直接返回
    else:
        return obj

使用方式:

import json

# 取出数据
instance = YourModel.objects.get(pk=1)
# 反序列化还原原始结构
original_data = json.loads(instance.a_math_function, object_hook=math_json_decoder)
# original_data 会是:[(inf, 1.0), (270, 0.9002), (0, 0.0)]

额外说明

  • 如果你不需要兼容Django的特殊类型(比如datetime),可以直接继承标准库的json.JSONEncoder,不用DjangoJSONEncoder。
  • 第三方库如simplejson虽然支持直接序列化inf,但PostgreSQL的jsonb仍然会拒绝这类值,所以转字符串标记是最稳妥的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:42:07