WebLogic 12c迁移应用:API返回null而非空JSON对象的实现求助
问题背景
将Java应用从WebLogic 11g迁移至12c后,API端点代码如下:
@GET @Path("/scheme/id/{Id}") @Produces(MediaType.APPLICATION_JSON) public List<Scheme> getSchemesById(@PathParam("Id") String id){ List<Scheme> list = new ArrayList<Scheme>(); return list; }
当前通过ObjectMapper配置了NON_NULL和NON_EMPTY规则,导致空列表返回{},但需求是空列表时返回null,且应用同时支持Jersey 1和Jersey 2。已尝试资源上下文配置ObjectMapper、给getter加@JsonInclude(ALWAYS)、自定义null序列化器,但未解决问题。
解决方案
1. 局部端点直接返回null(最简单方案)
如果仅需针对该端点处理,直接在方法内判断列表为空时返回null,无需修改序列化配置:
@GET @Path("/scheme/id/{Id}") @Produces(MediaType.APPLICATION_JSON) public List<Scheme> getSchemesById(@PathParam("Id") String id){ List<Scheme> list = new ArrayList<Scheme>(); // 空列表时返回null return list.isEmpty() ? null : list; }
2. 自定义集合序列化器(兼容Jersey 1/2)
创建专门处理空列表的序列化器,强制空列表输出null:
public class EmptyListToNullSerializer extends JsonSerializer<List<?>> { @Override public void serialize(List<?> list, JsonGenerator gen, SerializerProvider provider) throws IOException { if (list == null || list.isEmpty()) { gen.writeNull(); } else { gen.writeObject(list); } } }
全局生效方式
- Jersey 2:在
ResourceConfig中注册配置好的ObjectMapper
public class MyApplication extends ResourceConfig { public MyApplication() { ObjectMapper mapper = new ObjectMapper(); // 保留全局NON_NULL配置 mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 绑定自定义序列化器 SimpleModule module = new SimpleModule(); module.addSerializer(List.class, new EmptyListToNullSerializer()); mapper.registerModule(module); register(new JacksonJaxbJsonProvider(mapper, JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS)); // 注册资源类... } }
- Jersey 1:通过
ContextResolver提供自定义ObjectMapper
@Provider public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> { private final ObjectMapper mapper; public ObjectMapperContextResolver() { mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); SimpleModule module = new SimpleModule(); module.addSerializer(List.class, new EmptyListToNullSerializer()); mapper.registerModule(module); } @Override public ObjectMapper getContext(Class<?> type) { return mapper; } }
然后在web.xml的Jersey servlet配置中添加Provider包路径:
<servlet> <servlet-name>Jersey Servlet</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>你的资源包路径;你的Provider包路径</param-value> </init-param> <init-param> <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> <param-value>true</param-value> </init-param> </servlet>
单个端点生效方式
在目标端点方法上添加@JsonSerialize注解,指定使用自定义序列化器:
@GET @Path("/scheme/id/{Id}") @Produces(MediaType.APPLICATION_JSON) @JsonSerialize(using = EmptyListToNullSerializer.class) public List<Scheme> getSchemesById(@PathParam("Id") String id){ List<Scheme> list = new ArrayList<Scheme>(); return list; }
3. 局部覆盖序列化规则
在端点方法上添加@JsonInclude注解,强制覆盖全局NON_EMPTY配置:
@GET @Path("/scheme/id/{Id}") @Produces(MediaType.APPLICATION_JSON) @JsonInclude(JsonInclude.Include.ALWAYS) public List<Scheme> getSchemesById(@PathParam("Id") String id){ List<Scheme> list = new ArrayList<Scheme>(); return list; }
如果全局配置优先级更高,可结合上述自定义序列化器使用。
内容的提问来源于stack exchange,提问作者Swaraj Paul C
相关产品推荐
相关产品推荐

