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

cannot be cast to java.util.Map

java解析json字符串

怎么把json字符串转换map

JAVA 中 提取 alibaba.fastjson.JSONObject 字符串中的 KEY 和 VALUE 值