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

Flask Marshmallow SqlAlchemy使用Pluck时出现JSON序列化错误

使用Marshmallow Pluck字段序列化关联模型时出现JSON序列化错误

我有两个关联的SQLAlchemy模型(Product和TechnologyPillar),尝试用Marshmallow的Pluck字段在ProductSchema中返回关联的TechnologyPillar的特定字段,但序列化时抛出错误:TypeError: Object of type TechnologyPillar is not JSON serializable。移除technology_pillar字段时能正常返回数据,只要包含该字段就报错。

模型代码

from datetime import datetime
from typing import List
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class TechnologyPillar(db.Model):
    __tablename__ = "product_technology_pillars"

    id: db.Mapped[int] = db.mapped_column(primary_key=True)
    technology_pillar: db.Mapped[str] = db.mapped_column(db.String(150), nullable=False, unique=True)
    active_record: db.Mapped[bool] = db.mapped_column(db.Boolean)

    product: db.Mapped[List["Product"]] = db.relationship(back_populates="technology_pillar")

    def __repr__(self) -> str:
        return f"TechnologyPillar(id={self.id!r}, technology_pillar={self.technology_pillar!r})"

class Product(db.Model):
    __tablename__ = "products"

    id: db.Mapped[int] = db.mapped_column(primary_key=True)
    name: db.Mapped[str] = db.mapped_column(db.String(150), nullable=False, unique=True)
    fk_pillar_id = db.mapped_column(db.ForeignKey('product_technology_pillars.id'))
    technology_pillar: db.Mapped["TechnologyPillar"] = db.relationship(back_populates="product", lazy='joined', innerjoin=True)
    active_record: db.Mapped[bool] = db.mapped_column(db.Boolean, nullable=False)
    created_date: db.Mapped[datetime] = db.mapped_column(db.DateTime, default=datetime.utcnow)
    modified_date: db.Mapped[datetime] = db.mapped_column(db.DateTime, default=datetime.utcnow)

    def __repr__(self) -> str:
        return f"Product(" \
               f"id={self.id!r}, name={self.name!r})"

Schema代码(原错误版本)

from flask_marshmallow import Marshmallow

ma = Marshmallow()
class TechnologyPillarSchema(ma.SQLAlchemyAutoSchema):
    class Meta:
        fields = ("id", "technology_pillar")

class ProductSchema(ma.SQLAlchemyAutoSchema):
    class Meta:
        technology_pillar = ma.Pluck(TechnologyPillarSchema, 'technology_pillar')

        fields = ("id", "name", "technology_pillar")

主程序代码

from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy
from products.models import Product, TechnologyPillar
from products.schemas import ProductSchema, TechnologyPillarSchema


app = Flask(__name__)
db = SQLAlchemy(app)


technology_pillar_schema = TechnologyPillarSchema()
technologies_pillars_schema = TechnologyPillarSchema(many=True)

product_schema = ProductSchema()
products_schema = ProductSchema(many=True)


@app.route('/<id>', methods=['GET'])
def singleProduct(id):
    stmt = db.select(Product).where(Product.id == id)
    single_product = db.session.scalars(stmt).first()
    return product_schema.jsonify(single_product)

解决方案

错误的核心原因是Pluck字段的定义位置错误:你把technology_pillar = ma.Pluck(...)放在了Meta类内部,而Marshmallow只会识别Schema类直接定义的字段,Meta类仅用于配置Schema的元数据(比如fields、model等)。

修改后的ProductSchema应该把Pluck字段移到Meta类外部:

class ProductSchema(ma.SQLAlchemyAutoSchema):
    # 直接在Schema类下声明Pluck字段
    technology_pillar = ma.Pluck(TechnologyPillarSchema, 'technology_pillar')
    
    class Meta:
        fields = ("id", "name", "technology_pillar")

这样修改后,Marshmallow会正确使用Pluck字段提取关联的TechnologyPillar对象的technology_pillar字段值,而不是直接序列化整个对象,就能避免JSON序列化错误。

另外,你的模型中已经通过lazy='joined'配置了关联对象的即时加载,所以不需要额外处理关联数据的加载问题,确保序列化时能获取到关联对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 08:05:04