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

Springdoc如何自定义EntityModel返回结果的_links节点Schema?

解决Springdoc生成EntityModel时_links多余属性的问题

以下是几种无需自定义Response类的实现方式:

方案1:自定义OpenAPI Schema修改器

通过实现OpenApiCustomiser接口,直接修改生成的OpenAPI规范中_links的Schema结构,只保留需要的链接和href属性:

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.media.ObjectSchema;
import io.swagger.v3.oas.models.media.StringSchema;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class OpenApiConfig {

    @Bean
    public OpenApiCustomiser linksSchemaCustomiser() {
        return openApi -> {
            Components components = openApi.getComponents();
            // 找到EntityModel对应的Schema(名称格式为EntityModelOf[实体类名],这里假设是EntityModelOfRecipe)
            ObjectSchema entityModelSchema = (ObjectSchema) components.getSchemas().get("EntityModelOfRecipe");
            if (entityModelSchema != null) {
                // 自定义_links的Schema结构
                ObjectSchema linksSchema = new ObjectSchema();
                // 添加self链接,仅包含href
                ObjectSchema selfLinkSchema = new ObjectSchema();
                selfLinkSchema.addProperty("href", new StringSchema().example("/recipes/{id}"));
                linksSchema.addProperty("self", selfLinkSchema);
                // 添加recipes链接
                ObjectSchema recipesLinkSchema = new ObjectSchema();
                recipesLinkSchema.addProperty("href", new StringSchema().example("/recipes"));
                linksSchema.addProperty("recipes", recipesLinkSchema);
                // 添加ingredients链接
                ObjectSchema ingredientsLinkSchema = new ObjectSchema();
                ingredientsLinkSchema.addProperty("href", new StringSchema().example("/recipes/{id}/ingredients"));
                linksSchema.addProperty("ingredients", ingredientsLinkSchema);
                // 替换原有的_links Schema
                entityModelSchema.addProperty("_links", linksSchema);
            }
        };
    }
}

方案2:配置Jackson序列化规则限制Link输出

通过自定义Jackson序列化器,让Link对象仅序列化href属性,Springdoc会基于此生成符合要求的示例:

  1. 编写自定义Link序列化器:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.hateoas.Link;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class LinkSerializer extends JsonSerializer<Link> {
    @Override
    public void serialize(Link link, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("href", link.getHref());
        gen.writeEndObject();
    }
}
  1. 注册序列化器到Spring的ObjectMapper:
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.hateoas.Link;

@Configuration
public class JacksonConfig {

    @Bean
    public ObjectMapper objectMapper(LinkSerializer linkSerializer) {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new com.fasterxml.jackson.databind.module.SimpleModule()
                .addSerializer(Link.class, linkSerializer));
        return mapper;
    }
}

之后在接口中通过WebMvcLinkBuilder添加指定链接即可:

import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RecipeController {

    @GetMapping("/recipes/{id}")
    public EntityModel<Recipe> getRecipe(@PathVariable Long id) {
        Recipe recipe = new Recipe(); // 业务逻辑获取实体
        EntityModel<Recipe> entityModel = EntityModel.of(recipe);
        // 添加指定链接
        entityModel.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(RecipeController.class).getRecipe(id)).withSelfRel());
        entityModel.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(RecipeController.class).getAllRecipes()).withRel("recipes"));
        entityModel.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(RecipeController.class).getIngredients(id)).withRel("ingredients"));
        return entityModel;
    }

    // 省略getAllRecipes、getIngredients方法
}

方案3:直接用@Schema注解指定示例

在接口方法上通过@Schema注解直接定义返回示例,覆盖Springdoc自动生成的内容:

import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.hateoas.EntityModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RecipeController {

    @GetMapping("/recipes/{id}")
    @Schema(example = "{\"id\": 1, \"name\": \"Tomato Soup\", \"_links\": {\"self\": {\"href\": \"/recipes/1\"}, \"recipes\": {\"href\": \"/recipes\"}, \"ingredients\": {\"href\": \"/recipes/1/ingredients\"}}}")
    public EntityModel<Recipe> getRecipe(@PathVariable Long id) {
        // 业务逻辑和添加链接的代码同上
        return entityModel;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 05:05:38