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

SpringBoot项目Swagger-ui展示List<MonetaryAmount>为null的问题求助

解决Swagger展示List字段为null的问题

你遇到的问题本质是Swagger默认无法识别MonetaryAmount这类非标准JDK类型(比如Java Money API中的实现),而且directModelSubstitute只对单个类型生效,没法直接处理泛型集合里的元素。下面给你两种实用的解决方案,都能让Swagger-ui正确展示期望的{"currency":"EUR", "rate": 12.23}结构:

方案一:用@Schema注解直接定义字段结构(快速简单)

这种方法不需要额外编写复杂转换器,直接在实体字段上通过Swagger注解指定List元素的结构:

  1. 在你的实体类的rates字段上添加@Schema注解,明确数组元素的结构:
import io.swagger.v3.oas.annotations.media.Schema;

public class YourEntity {
    // 其他字段...
    
    @Schema(
        type = "array",
        items = @Schema(
            type = "object",
            properties = {
                @Schema(name = "currency", type = "string", description = "货币代码,比如EUR"),
                @Schema(name = "rate", type = "number", format = "double", description = "汇率数值")
            }
        )
    )
    private List<MonetaryAmount> rates;

    // getter、setter方法
}
  1. 配置Jackson序列化,确保接口实际返回的JSON和Swagger展示的结构一致:
    创建一个Jackson配置类,把MonetaryAmount序列化为期望的键值对:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.javamoney.moneta.MonetaryAmount;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

@Configuration
public class JacksonConfig {
    @Bean
    public SimpleModule monetaryAmountSerializerModule() {
        SimpleModule module = new SimpleModule();
        module.addSerializer(MonetaryAmount.class, new JsonSerializer<MonetaryAmount>() {
            @Override
            public void serialize(MonetaryAmount value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                gen.writeStartObject();
                // 提取货币代码
                gen.writeStringField("currency", value.getCurrency().getCurrencyCode());
                // 提取汇率数值,转成double(根据需求也可以用BigDecimal)
                gen.writeNumberField("rate", value.getNumber().doubleValue());
                gen.writeEndObject();
            }
        });
        return module;
    }
}

方案二:全局自定义ModelResolver(适合多处使用MonetaryAmount的场景)

如果你的项目里很多地方都用到了MonetaryAmount,可以全局配置Swagger的类型解析器,一次性解决所有地方的展示问题:

  1. 创建自定义的ModelResolver,让Swagger识别MonetaryAmount和List<MonetaryAmount>:
import io.swagger.v3.core.converter.ModelConverterContext;
import io.swagger.v3.core.jackson.ModelResolver;
import io.swagger.v3.core.model.ParameterizedType;
import io.swagger.v3.core.model.Schema;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.NumberSchema;
import io.swagger.v3.oas.models.media.ObjectSchema;
import io.swagger.v3.oas.models.media.StringSchema;
import org.javamoney.moneta.MonetaryAmount;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.List;

@Configuration
public class SwaggerConfig {

    @Bean
    public ModelResolver customModelResolver() {
        return new ModelResolver(null) {
            @Override
            public Schema resolve(Type type, ModelConverterContext context, Iterator<ModelConverter> chain) {
                // 处理单个MonetaryAmount类型
                if (type.getTypeName().equals(MonetaryAmount.class.getTypeName())) {
                    ObjectSchema schema = new ObjectSchema();
                    schema.addProperty("currency", new StringSchema().description("货币代码"));
                    schema.addProperty("rate", new NumberSchema().format("double").description("汇率数值"));
                    return schema;
                }
                // 处理List<MonetaryAmount>类型
                if (type instanceof ParameterizedType) {
                    ParameterizedType paramType = (ParameterizedType) type;
                    if (List.class.isAssignableFrom((Class<?>) paramType.getRawType())) {
                        Type[] genericTypes = paramType.getActualTypeArguments();
                        if (genericTypes.length > 0 && genericTypes[0].getTypeName().equals(MonetaryAmount.class.getTypeName())) {
                            // 递归解析泛型元素的Schema
                            Schema<?> itemSchema = resolve(genericTypes[0], context, chain);
                            return new ArraySchema().items(itemSchema);
                        }
                    }
                }
                // 其他类型交给默认解析器处理
                return super.resolve(type, context, chain);
            }
        };
    }
}
  1. 同样需要配置上面的Jackson序列化类,保证实际返回数据的格式正确。

这两种方案都能解决你遇到的问题:方案一适合快速解决单个字段的问题,方案二更适合全局统一处理。测试一下,Swagger-ui里的rates字段就会显示成你期望的数组结构,而不是[null]了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:04:36