如何使用CRNK IO在响应JSON中添加额外根级变量
Crnk.io 调整响应结构将字段提升至根级配置方法
问题场景
当前接口响应结构(注:原示例JSON存在语法错误,数组内无法直接定义键值对,实际countries嵌套在data对应的资源属性中):
{ "data" : [ // countries字段嵌套在data域内 "countries":[] ] }
期望响应结构,countries与data为同级根字段:
{ "data": [], "countries" : [] }
Crnk默认遵循JSON:API规范,响应顶级节点仅保留规范约定的data/errors/meta/links字段,要实现上述结构调整,可通过以下两种方式实现:
方案1:通过RepositoryFilter修改响应顶级属性(推荐,兼容原生Crnk特性)
Crnk提供了仓库请求过滤器扩展点,可在响应序列化前修改最终返回的顶级结构,步骤如下:
- 编写自定义过滤器,在过滤器中取出嵌套在资源内的
countries数据,直接设置到响应顶级节点,同时删除data内冗余的countries属性,示例代码:
import io.crnk.core.engine.filter.RepositoryFilterBase; import io.crnk.core.engine.filter.RepositoryFilterContext; import io.crnk.core.engine.filter.RepositoryRequestFilterChain; import io.crnk.core.repository.response.JsonApiResponse; import java.util.List; public class CountriesTopLevelFilter extends RepositoryFilterBase { @Override public JsonApiResponse filterRequest(RepositoryFilterContext context, RepositoryRequestFilterChain chain) { JsonApiResponse response = chain.doFilter(context); Object entityData = response.getEntity(); List countriesData = null; // 根据自身业务逻辑从返回的实体数据中提取countries字段值 // 示例:如果返回的单资源/列表资源内包含countries属性,在此处完成取值 /* if (entityData instanceof YourResource) { countriesData = ((YourResource) entityData).getCountries(); } else if (entityData instanceof List) { List<?> dataList = (List<?>) entityData; if (!dataList.isEmpty() && dataList.get(0) instanceof YourResource) { countriesData = ((YourResource) dataList.get(0)).getCountries(); } } */ // 将countries设置为顶级响应字段 response.setTopLevel("countries", countriesData); return response; } }
- 将自定义过滤器注册到Crnk上下文,以Spring Boot集成场景为例,直接将过滤器注册为Spring Bean即可被Crnk自动扫描加载:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class CrnkCustomConfig { @Bean public CountriesTopLevelFilter countriesTopLevelFilter() { return new CountriesTopLevelFilter(); } }
方案2:替换默认序列化器(不推荐,会破坏JSON:API规范兼容)
如果项目不需要遵循JSON:API规范,可以直接替换Crnk默认的JsonApiDocumentSerializer序列化实现,自定义JSON生成逻辑,手动构建包含data和countries同级节点的响应结构。该方式会丢失Crnk默认提供的分页、错误处理、关联资源加载等原生能力,仅适合完全自定义接口格式的场景。
内容的提问来源于stack exchange,提问作者ashish mohanty
相关产品推荐
相关产品推荐

