Umarshall JSON对象,包含Jackson和JAXB之间的下划线和camelCase字段

时间:2014-02-24 17:51:14

标签: jaxb jackson

使用JAXB(2.2)和Jackson(1.9.13),我无法将以下JSON对象解组到我的POJO

{
   "userId": "foo",
   "group_id": "bar"
}

请注意,有效内容包含camelCase和下划线字段。

xjc为我的XML模式生成的POJO如下:

public class User {
    @XmlElement(required = true)
    protected String userId;
    @XmlElement(name = "group_id", required = true)
    protected String groupId;

    public String getUserId() { return userId; }       
    public void setUserId(String value) { this.userId = value; }
    public String getGroupId() { return groupId; }
    public void setGroupId(String value) { this.groupId = value; }
}

杰克逊因以下例外而失败:

org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "group_id"

到目前为止我尝试了什么

1。使用JAXB绑定underscoreBinding="asCharInWord"

在我的XML架构中使用以下JXB绑定

<jxb:globalBindings underscoreBinding="asCharInWord"/>

生成以下POJO:

public class User {
    @XmlElement(required = true)
    protected String userId;
    @XmlElement(name = "group_id", required = true)
    protected String groupId;

    public String getUserId() { return userId; }
    public void setUserId(String value) { this.userId = value; }
    public String getGroup_Id() { return groupId; }
    public void setGroup_Id(String value) { this.groupId = value; }
}

请注意,JAXB现在为组ID生成带下划线的setter / getter,但group_id字段仍然转换为CamelCase。杰克逊的对象映射器似乎忽略了属性getter / setter名称,仍然无法将group_id映射到groupId

2。杰克逊财产命名策略

使用杰克逊的PropertyNamingStrategy CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES我可以将group_id转换为groupId,但现在对象映射器在userId JSON属性上失败。

3。向groupId

添加JSONProperty注释

JSONProperty添加到vanilla JAXB生成的POJO实际上可以正常工作

public class User {
        /* ... */
        @XmlElement(name = "group_id", required = true)
        @JSONProperty("group_id")
        protected String groupId;
        /* ... */
   }

但是,我的XML模式非常庞大,并且生成的类的手动检测是不可行的,因为我们经常生成类。

我该怎么办?

我看到以下两个选项可以解决这个问题:

  1. 实现一个JAXB插件,为每个JSONProperty添加一个带有下划线名称的XMLElement注释(我的首选下一个方法)
  2. this Stackoverflow答案中所述,为XJC使用自定义名称生成器。
  3. 我错过了明显的事吗? 谢谢你的想法。

2 个答案:

答案 0 :(得分:4)

您是否尝试使用groupId在用户类中注释@JsonProperty("group_id")属性。这应该有效(经过测试和验证)!

如果属性上没有这样的注释,Jackson映射器将只考虑属性名称,否则提供的值将用于JSON反序列化。以下是您应该查看User班级的信息:

public class User {

private String userId;

@JsonProperty("group_id")
private String groupId;

这应该映射到您的JSON

{"userId": "foo","group_id": "bar"}

如果您正在使用基于Jackson的CXF(或任何其他Rest框架),我建议您阅读以下简短的博客文章,其中详细介绍了如何在CXF中配置JacksonJsonProvider以实现从/到Java的序列化和反序列化到JSON Snake Case(下划线)格式化数据

https://mahichir.wordpress.com/2015/07/08/cxf-configuration-to-produce-json-snake-case-underscore-case-formatted-data-using-jackson-json-library/

答案 1 :(得分:0)

我发现了一个可能的问题解决方案,从类似的情况来看,在stackoverflow上。 How to extract ObjectMapper from JAX-RS Client?

访问Object Mapper后,您可以设置自己的注释提供程序。现在,作为一个单独的模块已被删除,因为jackson 2.0是jaxb模块。

这里是答案,虽然我修改了它,因此它符合Jackson模块Jaxb 2.4.4和Jackson API 2.3.2:

public final static JacksonJsonProvider JACKSON_JSON_PROVIDER = new JacksonJaxbJsonProvider().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
public final static ObjectMapper OBJECT_MAPPER = JACKSON_JSON_PROVIDER.locateMapper(Object.class, MediaType.APPLICATION_JSON_TYPE);
public final static Client CLIENT = ClientBuilder.newClient().register(JACKSON_JSON_PROVIDER);

这需要jar:jackson-module-jaxb-annotations-2.x.x.jar,所以jackson可以通过JacksonJaxbProvider接口将它加载到场景后面。

对于你的Jackson版本,我认为jaxb代码仍在其中。因此,您可以使用http://wiki.fasterxml.com/JacksonJAXBAnnotations

来引用类似的方式