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

调用json.dumps序列化EXIF信息时遇IFDRational类型不可序列化错误

解决EXIF信息JSON序列化报错(IFDRational类型)

问题原因

你碰到的TypeError: Object of type IFDRational is not JSON serializable,是因为部分图片的EXIF字段值是PIL库的IFDRational分数对象,而Python标准json.dumps()无法直接序列化这种自定义类型。你打印的字典里XResolution和YResolution是72.0(float类型),但出错的图片中这类字段实际是IFDRational实例,而非直接数值。

解决方案

方式1:生成EXIF字典时直接转换类型

在构建字典的过程中,判断并转换IFDRational为可序列化的数值类型:

from PIL import Image, ExifTags
import json

image_open = Image.open(self.image)
image_open.verify()
image_getexif = image_open.getexif()
if image_getexif:
    exif = {}
    for k, v in image_getexif.items():
        if k not in ExifTags.TAGS:
            continue
        # 处理IFDRational类型,转成float
        if hasattr(v, 'numerator') and hasattr(v, 'denominator'):
            v = float(v.numerator / v.denominator)
        elif isinstance(v, bytes):
            continue
        exif[ExifTags.TAGS[k]] = v
    print(json.dumps(exif, indent=4))

方式2:自定义JSON编码器

如果需要兼容更多PIL自定义类型,可编写专属编码器:

from PIL import Image, ExifTags
import json
from PIL.ExifTags import IFDRational

class ExifJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, IFDRational):
            return float(obj.numerator / obj.denominator)
        # 如需处理GPS相关的分数类型,可添加GPSIFDRational的判断
        return super().default(obj)

# 使用示例
image_open = Image.open(self.image)
image_open.verify()
image_getexif = image_open.getexif()
if image_getexif:
    exif = {
        ExifTags.TAGS[k]: v for k, v in image_getexif.items() 
        if k in ExifTags.TAGS and not isinstance(v, bytes)
    }
    print(json.dumps(exif, indent=4, cls=ExifJSONEncoder))

补充说明

不同设备生成的EXIF存储格式存在差异:部分设备直接存储数值,部分设备会以IFDRational分数形式存储分辨率等参数,这就是为什么只有部分图片报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 03:10:37