Java.util.Map to JSON Object with Jersey / JAXB / Jackson
Posted
技术标签:
【中文标题】Java.util.Map to JSON Object with Jersey / JAXB / Jackson【英文标题】: 【发布时间】:2011-08-13 06:37:24 【问题描述】:我一直在尝试创建 Jersey REST Web 服务。我想从 Java 类接收和发出 JSON 对象,如下所示:
@XmlRootElement
public class Book
public String code;
public HashMap<String, String> names;
这应该像这样转换成 JSON:
"code": "ABC123",
"names":
"de": "Die fabelhafte Welt der Amelie",
"fr": "Le fabuleux destin d'Amelie Poulain"
但是我找不到一个标准的解决方案。每个人似乎都在实现自己的wrappersolution。这个要求对我来说似乎非常基本;我不敢相信这是普遍接受的解决方案,尤其是因为 Jersey 确实是 Java 中更有趣的部分之一。
我还尝试升级到 Jackson 1.8,它只给了我这个,这是极度混淆的 JSON:
"code": "ABC123",
"names":
"entry": [
"key": "de",
"value": "Die fabelhafte Welt der Amelie"
,
"key": "fr",
"value": "Le fabuleux destin d'Amelie Poulain"
]
对此有什么建议的解决方案吗?
【问题讨论】:
【参考方案1】:我知道很久以前就有人问过了,但是事情发生了变化,所以对于没有包 com.sun.jersey 的最新 Jersey v2.22,添加了这两个依赖项在项目中 pom.xml 解决了同样的问题:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.5.4</version> <!-- jackson version used by jersey v2.22 -->
</dependency>
无需在 web.xml 中添加任何内容。 第一个依赖项将指示 jersey 使用 jackson 进行 POJO 到 JSON 的转换。 第二个依赖项会将 jackson 注册为 jersey JSON 提供程序。
同样针对POJO中的null问题,在POJO类中加入这个注解:
@JsonInclude(JsonInclude.Include.NON_NULL)
【讨论】:
【参考方案2】:我不知道为什么这不是默认设置,我花了一段时间才弄清楚,但如果你想使用 Jersey 进行 JSON 转换,请添加
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
到您的 web.xml,您的所有问题都应该得到解决。
PS:你还需要去掉 @XmlRootElement
注释才能让它工作
【讨论】:
小费+1。但请注意,POJO 映射也会在 JSON 中返回 NULL 值。我更喜欢 JAXB 并使用包含额外 POJO 的列表。 这是服务器端设置。在客户端上执行此操作: ClientConfig clientConfig = new DefaultClientConfig(); clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);客户端client = Client.create(clientConfig); @Jan 如果我需要将 Book 转换为 json 和 xml(带有 accepts 的请求)怎么办?如果我删除 XmlRootElement xml 序列化不再起作用 哇。这将是一个很好的答案,除了按照建议添加到 web.xml,无论是否删除 @XmlRootElement 和相关注释都会导致:com.sun.jersey.spi.container.ContainerRequest getEntity SEVERE: A message body reader for Java com.hp.web.user.dto.ProfileDto 类和 Java 类型 com.hp.web.user.dto.ProfileDto 类和 MIME 媒体类型 application/json; charset=UTF-8 未找到。 是的,Russ 说的。此非解决方案给出“未找到消息正文编写器”错误【参考方案3】:@POST
@Consumes("application/json")
public void createBook(Book book)
.....
.....
当然,您需要为 Book 中的每个属性设置 getter/setter。
推荐使用包装类(通常是一个映射)的原因也是为了避免为您要发送的每种数据创建多个 DTO。使用映射进行序列化/反序列化并作为业务逻辑的一部分将其转换为相应的 POJO 以进行内部处理更容易,特别是如果您使用该 POJO 进行对象关系映射。
【讨论】:
【参考方案4】:您可以使用google-gson。这是一个示例代码:
@Test
public void testGson()
Book book = new Book();
book.code = "1234";
book.names = new HashMap<String,String>();
book.names.put("Manish", "Pandit");
book.names.put("Some","Name");
String json = new Gson().toJson(book);
System.out.println(json);
输出为"code":"1234","names":"Some":"Name","Manish":"Pandit"
【讨论】:
谢谢,但我对与 Jersey 集成的解决方案特别感兴趣。 我更喜欢这种返回复杂数据结构的方法,而不是简单的 POJO。它完美地工作,它与 Jersey 集成(你只需要在你的 get 方法中返回一个“字符串”),你不必搞乱转换器的 web.xml。以上是关于Java.util.Map to JSON Object with Jersey / JAXB / Jackson的主要内容,如果未能解决你的问题,请参考以下文章
从 json 编码/解码到 java.util.Map 的库?
cannot be cast to java.util.Map