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

use*_*943 18 jaxb jackson

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

{
   "userId": "foo",
   "group_id": "bar"
}
Run Code Online (Sandbox Code Playgroud)

请注意,有效负载包含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; }
}
Run Code Online (Sandbox Code Playgroud)

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

org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "group_id"
Run Code Online (Sandbox Code Playgroud)

到目前为止我尝试过但失败了

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

在我的XML模式中使用以下JXB绑定

<jxb:globalBindings underscoreBinding="asCharInWord"/>
Run Code Online (Sandbox Code Playgroud)

生成以下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; }
}
Run Code Online (Sandbox Code Playgroud)

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

2.杰克逊财产命名策略

使用Jackson的PropertyNamingStrategy CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES我可以转换group_idgroupId,但现在对象映射器在userIdJSON属性上失败.

3. JSONProperty向groupId 添加注释

添加JSONProperty到vanilla JAXB生成的POJO实际上是有效的

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

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

我该怎么办?

我看到以下两个剩余的选项来处理这个问题:

  1. 实现一个JAXB插件,JSONProperty为每个XMLElement下划线名称添加一个注释(我的首选下一个方法)
  2. 如此 Stackoverflow答案中所述,为XJC使用自定义名称生成器.

我错过了明显的吗?谢谢你的想法.

Mah*_*hir 5

您是否尝试过使用注释groupId用户类中的属性@JsonProperty("group_id")。这应该工作(经过测试和证明)!

如果属性上不存在此类注释,Jackson映射器将仅按原样考虑属性名称,否则提供的值将用于JSON反序列化。这是您的User班级外观:

public class User {

private String userId;

@JsonProperty("group_id")
private String groupId;
Run Code Online (Sandbox Code Playgroud)

这应该映射到您的JSON

{"userId": "foo","group_id": "bar"}
Run Code Online (Sandbox Code Playgroud)

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

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


小智 0

我在 stackoverflow 上从类似的案例中找到了您的问题的可能解决方案。 如何从 JAX-RS 客户端提取 ObjectMapper?

一旦您有权访问对象映射器,您就可以设置自己的注释提供程序。现在已将其作为单独的模块删除,因为 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);
Run Code Online (Sandbox Code Playgroud)

这需要 jar:jackson-module-jaxb-annotations-2.xxjar,以便 jackson 可以通过 JacksonJaxbProvider 接口在后台加载它。

对于您的 Jackson 版本,我认为 jaxb 代码仍在其中。所以你可以参考类似的方式使用http://wiki.fasterxml.com/JacksonJAXBAnnotations