Jersey 2与Jackson注解@JsonIgnore:两JSON依赖冲突需同时使用
我之前也碰到过类似的坑——两个JSON处理模块版本不兼容加上Jersey自动注册的机制,确实会让Jackson的注解(比如@JsonIgnore)失效得莫名其妙。你的核心问题有两个:一是依赖版本严重不一致(jersey-media-json-binding用2.27,jersey-media-json-jackson却用2.3.1),二是Jersey会自动注册多个JSON消息体提供者,导致Jackson的注解逻辑被JSON-B覆盖。下面是一步步的解决方案:
1. 统一所有Jersey依赖版本
版本差异是冲突的根源,2.3.1是非常老旧的Jackson模块版本,和2.27的Jersey核心完全不兼容。先把所有相关依赖的版本统一成同一个:
<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-binding</artifactId> <version>2.27</version> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>2.27</version> <!-- 和binding模块版本严格一致 --> </dependency>
如果你的项目里有Jersey核心依赖(比如jersey-server),也必须确保它的版本和这两个保持一致,避免连锁冲突。
2. 解决JSON提供者的竞争问题
Jersey的AutoDiscoverable机制会自动扫描并注册所有可用的JSON处理器,这会导致JSON-B和Jackson互相抢着处理请求/响应,最终Jackson的注解失效。你有两种可靠的解决方式:
方式一:排除JSON-B的自动注册器
在pom.xml里给jersey-media-json-binding添加排除,去掉它的自动注册类,让Jackson成为默认的JSON处理器:
<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-binding</artifactId> <version>2.27</version> <exclusions> <exclusion> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-binding-autodiscoverable</artifactId> </exclusion> </exclusions> </dependency>
方式二:手动注册Jackson特性并禁用自动发现
在你的Jersey应用配置类里,明确注册Jackson的JacksonFeature,同时只加载你需要的资源类,避免自动扫描带来的冲突:
import org.glassfish.jersey.jackson.JacksonFeature; import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; import java.util.HashSet; import java.util.Set; @ApplicationPath("/api") public class MyJerseyApp extends Application { @Override public Set<Class<?>> getClasses() { Set<Class<?>> classes = new HashSet<>(); // 强制注册Jackson特性,确保优先使用Jackson处理JSON classes.add(JacksonFeature.class); // 添加你的业务资源类 classes.add(UserResource.class); classes.add(OrderResource.class); return classes; } }
如果用web.xml配置Jersey,可以添加以下参数指定Jackson优先:
<servlet> <servlet-name>Jersey Servlet</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.classnames</param-name> <param-value>org.glassfish.jersey.jackson.JacksonFeature</param-value> </init-param> </servlet>
3. 验证注解是否生效
完成配置后,测试你的实体类中的@JsonIgnore是否正常工作:
public class User { private String username; @JsonIgnore // 这个字段应该不会被序列化到JSON中 private String password; // getter/setter方法 }
当你返回User对象作为响应时,password字段应该不会出现在JSON结果里。
额外排查点
如果还是有问题,可以检查:
- 实体类的getter/setter是否符合Jackson的命名规范(比如
getPassword()对应password字段) - 项目中是否引入了其他JSON处理库(比如Gson),导致额外冲突
- 开启Jersey的调试日志,查看哪个
MessageBodyWriter被选中处理JSON响应,确认是Jackson的实现
内容的提问来源于stack exchange,提问作者Anderson Oki

