如何在进行 Jackson 反序列化时将 JSON 字段名称转换为 Java 兼容的 属性 名称?

How to covert JSON field name to a Java compatible property name while doing Jackson de-serialisation?

我有 ServerDetails pojo class。

package org.vo;

import org.codehaus.jackson.annotate.JsonProperty;

public class ServerDetails {

    private Integer serverId;
    private String server_url;

    public ServerDetails() {

    }

    public ServerDetails(Integer serverId, String server_url) {
        this.serverId = serverId;
        this.server_url = server_url;
    }

    @JsonProperty("server-id")
    public Integer getServerId() {
        return serverId;
    }


    public void setServerId(Integer serverId) {
        this.serverId = serverId;
    }

    @JsonProperty("server-url")
    public String getServer_url() {
        return server_url;
    }

    public void setServer_url(String server_url) {
        this.server_url = server_url;
    }

}

我使用 Jackson API 将 ServerDetails 对象转换为 JSON 并使用 @JsonProperty 注释自定义 JSON 字段名称。所以我生成的 JSON 和预期的一样

{
   "server-id":1,
   "server-url":"http://whosebug.com"
}

虽然在 pojo class 中属性是 serverId 和 server_url 但在生成的 JSON 中字段是 server-id 和 server-url 因为我已经应用了两个属性的 getter 方法上的 @JsonProperty 注释。

现在一切都还好。

但是当我试图将相同的 JSON 转换为 Java 时,我遇到了以下错误

org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "server-id" (Class org.vo.ServerDetails), not marked as ignorable
 at [Source: D:\tmp\ServerDetails.json; line: 1, column: 15] (through reference chain: org.vo.ServerDetails["server-id"])
    at org.codehaus.jackson.map.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:53)
    at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:244)
    at org.codehaus.jackson.map.deser.StdDeserializer.reportUnknownProperty(StdDeserializer.java:605)
    at org.codehaus.jackson.map.deser.StdDeserializer.handleUnknownProperty(StdDeserializer.java:591)
    at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty(BeanDeserializer.java:684)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:515)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:351)
    at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2130)
    at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1348)
    at org.converter.JSONToJavaExample.main(JSONToJavaExample.java:16)

不知何故我无法弄清楚我需要做什么来解决这个问题 issue.I 只想从生成的 JSON.

中取回 ServerDetails 对象

下面是我的 JSON 到 java 对象转换的代码。

import java.io.File;
import java.io.IOException;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.vo.ServerDetails;

public class JSONToJavaExample {
    public static void main(String[] args) {
        ServerDetails serverDetails = null;
        ObjectMapper mapper = new ObjectMapper();
        try {
            serverDetails = mapper.readValue(new File(
                    "D:/tmp/ServerDetails.json"), ServerDetails.class);
        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

我正在使用 jackson-all-1.7.6.jarjdk1.8.0_31

问题已解决,sotirios-delimanolis and staxman 都得到了充分的肯定。一般来说,人们喜欢找到直接的答案,而不是真的喜欢浏览评论,尽管实际答案可以出现在这些评论中。所以这个答案是专门为那些喜欢直接找到答案的用户准备的。

如果您使用 Jackson 转换 JSON to/from Java 对象并且 Jackson API 版本低于 1.8 然后你需要注释 both getter 和 setter 方法 @JsonProperty if JSON field names and Java 属性 名称不同。

所以,我已经用 @JsonProperty 注释对 setter 方法进行了注释。下面是修改后的代码(ServerDetails.java)

@JsonProperty("server-id")
public Integer getServerId() {
    return serverId;
}

// added
@JsonProperty("server-id")
public void setServerId(Integer serverId) {
    this.serverId = serverId;
}

@JsonProperty("server-url")
public String getServer_url() {
    return server_url;
}

// added
@JsonProperty("server-url")
public void setServer_url(String server_url) {
    this.server_url = server_url;
}

如果你想避免这种额外的工作,那么你需要升级你的jackson-all jar 版本并且版本应该高于1.7

为什么?为什么高于 1.7?

用斯塔克斯曼的话来说

key difference is 1.7 vs 1.8: latter added code to "unify" annotations, so you do not need to add renaming for both getter and setter. With 1.7 you would need to add annotation for both, and your class only had them for one. So, not technically a bug (it was defined behavior), but missing functionality.

希望这个回答能对遇到同样问题的人有所帮助。