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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 11:55:17