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元素的结构:
- 在你的实体类的
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方法 }
- 配置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的类型解析器,一次性解决所有地方的展示问题:
- 创建自定义的
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); } }; } }
- 同样需要配置上面的Jackson序列化类,保证实际返回数据的格式正确。
这两种方案都能解决你遇到的问题:方案一适合快速解决单个字段的问题,方案二更适合全局统一处理。测试一下,Swagger-ui里的rates字段就会显示成你期望的数组结构,而不是[null]了。
内容的提问来源于stack exchange,提问作者smaiakov
相关产品推荐
相关产品推荐

