【问题标题】:How to get both JSON and XML response in Jersey having root element in both the cases?在这两种情况下,如何在 Jersey 中获得具有根元素的 JSON 和 XML 响应?
【发布时间】:2025-12-28 18:25:16
【问题描述】:

我想通过使用单个函数来响应:

@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getVolume(){
    ...enter code here
    return Response.ok().entity(VolDetail).build();
}

输出应该是这样的:

xml:
<volume>
   <status>available</status>
</volume>

JSON:
{"volume":{"status":"available"}}

volume 是一个 POJO 类。

问题是我没有在 JSON 中获取根元素。我尝试了 JSON 对象绑定,但它无法正常工作。

【问题讨论】:

  • 您使用的是什么 JSON 提供程序。你能显示你的依赖关系吗
  • 我的 pojo 类:@XmlRootElement(name="volume") @JsonRootName(value="volume") public class VolumeDetail { public String status;
  • 感谢您的回复..!!我的 pojo 类:@XmlRootElement(name="volume") @JsonRootName(value="volume") public class VolumeDetail { public String status;我在上面提到的 getVolume() 函数中尝试了这个以在日志中打印: ObjectMapper om = new ObjectMapper().enable(SerializationConfig.Feature.WRAP_ROOT_VALUE);字符串 jsonResponse = om.writeValueAsString(response); _log.info(jsonResponse);
  • 见下面的答案。我已经测试过了,效果很好

标签: java xml json jersey jax-rs


【解决方案1】:

假设您使用的是 Jackson。您可以将ObjectMapper 配置为WRAP_ROOT_VALUE。您可以在ContextResolver 中执行此操作。使用 Jackson 1.x,它看起来像

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig.Feature;

@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper>  {
    
    final ObjectMapper mapper = new ObjectMapper();
    
    public ObjectMapperContextResolver() {
        mapper.configure(Feature.WRAP_ROOT_VALUE, true);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return mapper;
    }  
}

使用 Jackson 2.x,它看起来像

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper>  {
    
    final ObjectMapper mapper = new ObjectMapper();
    
    public ObjectMapperContextResolver() {
        mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return mapper;
    }  
}

您的 POJO 应使用 @XmlRootElement(name = "volume")@JsonRootName("volume") 注释

如果您不想包装所有对象,您可以为不同的类配置不同的映射器,如seen here

编辑

使用上述解决方案,只有@JsonRootName 可以工作。原因是通过使用我们自己的ObjectMapper,我们覆盖了 JAXB 注释支持配置的行为。我们可以通过mapper.registerModule(new JaxbAnnotationModule()); 明确添加支持

【讨论】:

  • 我实现了这个 ObjectMapperContextResolver。但它既不是调用 getContext() 也不是构造函数。我没有得到任何关于它将如何附加到我的 pojo 或资源类的关系。
  • 您是如何进行配置的?您的@Path 课程是如何被发现的?你可以用同样的方法注册这个类。使用包扫描或显式注册它。还要确保您使用的是正确的 Jackson 版本。如果您仍然需要帮助,请使用您的配置(web.xml 或 ResourceConfig)更新您的原始帖子并显示您的所有依赖项。不要在 cmets 中放置任何更新。您的帖子下方有一个“编辑”链接,用于添加更新
  • 就关系而言,JAX-RS 使用MessageBodyWriters 和MessageBodyReaders 来编组和解组。在请求资源的情况下,使用的MessageBodyWriter(由Jackson 提供)将看到响应是Volume 类型,并在ContextResolver 上调用getContext,传入类。您可以使用该类来检查要使用的映射器。在上面的情况下,不管什么类,都会使用相同的映射器
  • 其实我们是使用spring框架进行初始化的。我认为我们只是给出了路径@Path,它会自动出现在相应的 get 或 post 方法中。实际上我得到了两种格式的响应,但唯一的问题是我想要 JSON 格式的根元素。你能建议我如何实例化 ObjectMapperContextResolver 类并将我的 POJO 类注册到它。我找到了这篇文章,但在这里他们也在 main 方法中实例化:*.com/questions/18872931/…
  • 再次,如果您需要帮助,请显示您的配置。我可以向您展示四种不同的配置方式,但它可能不适合您当前的配置。泽西岛需要一些泽西岛配置才能工作。如果您完全不知道,请从 web.xml 开始。如果你没有,那么你必须有一个 ResourceConfig/Application 子类。并显示所有依赖项。没有那个,我帮不了你。我不想发布四种不同的可能配置,它们可能有效,也可能无效。
最近更新 更多