【问题标题】:Jackson ignoring XmlElement name/case when marshalling JSON杰克逊在编组 JSON 时忽略 XmlElement 名称/大小写
【发布时间】:2017-10-05 18:16:41
【问题描述】:

我正在尝试从 XSD->POJO->JSON 使用区分大小写的 UPS 跟踪 API。我在生成的 JSON 中使用 Jackson 2.6.7。当我应该在下面看到时,我会看到骆驼案例名称:

"TrackRequest": { "InquiryNumber": "1Z12345E6205277936" }

生成的 Java bean 如下注解:

@XmlElement(name = "TrackRequest")
protected TrackRequest trackRequest;

我尝试了一些映射功能设置,例如 USE_WRAPPER_NAME_AS_PROPERTY_NAME 和 USE_STD_BEAN_NAMING,但似乎没有达到预期的效果。

我正在像这样生成 JSON:

ObjectMapper mapper = new ObjectMapper();
String jsonRequest = mapper.writeValueAsString(upsRequest);

upsRequest bean 如下所示:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "upsSecurity",
    "trackRequest"
})
@XmlRootElement(name = "Request")
public class Request {

    @XmlElement(name = "UPSSecurity")
    protected UPSSecurity upsSecurity;
    @XmlElement(name = "TrackRequest")
    protected TrackRequest trackRequest;

    /**
     * Gets the value of the upsSecurity property.
     * 
     * @return
     *     possible object is
     *     {@link UPSSecurity }
     *     
     */
    public UPSSecurity getUPSSecurity() {
        return upsSecurity;
    }

    /**
     * Sets the value of the upsSecurity property.
     * 
     * @param value
     *     allowed object is
     *     {@link UPSSecurity }
     *     
     */
    public void setUPSSecurity(UPSSecurity value) {
        this.upsSecurity = value;
    }

    /**
     * Gets the value of the trackRequest property.
     * 
     * @return
     *     possible object is
     *     {@link TrackRequest }
     *     
     */
    public TrackRequest getTrackRequest() {
        return trackRequest;
    }

    /**
     * Sets the value of the trackRequest property.
     * 
     * @param value
     *     allowed object is
     *     {@link TrackRequest }
     *     
     */
    public void setTrackRequest(TrackRequest value) {
        this.trackRequest = value;
    }

}

根据文档,我应该得到想要的输出,除非我遗漏了什么

【问题讨论】:

  • 您也可以随时尝试添加 JSON 注释,例如@JsonProperty("TrackRequest")。如果它在现场不起作用,请尝试使用 getter 方法。
  • 我之前尝试过,它确实创建了所需的属性,但仍然创建了其他不需要的属性。

标签: java json xsd jersey jackson


【解决方案1】:

要使用此功能读取spring-boot 及其Jackson2ObjectMapperBuilder 中的@JsonPropertyXmlElement,您可以轻松地创建一个Bean,以便在每次需要时获取Builder。

@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    //configure features for serialization and deserialization
    return builder;
}

您现在可以自动装配构建器并在需要的地方直接配置 ObjectMapper:

@Component
public class MyClass {

    private ObjectMapper objectMapper;

    public MyClass(Jackson2ObjectMapperBuilder jacksonBuilder) {
        super();
        objectMapper = jacksonBuilder.build().registerModule(new JaxbAnnotationModule());
    }

    public String serialize(){
        AnyObject ao = new AnyObject();
        String json = objectMapper.writeValueAsString(ao);
        return json;
    }
}

【讨论】:

    【解决方案2】:

    默认情况下不支持 JAXB 注释。您需要添加jackson-module-jaxb-annotations 模块,然后将其注册到ObjectMapper

    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JaxbAnnotationModule());
    

    【讨论】:

    • 这行得通。 ObjectMapper 现在准确地命名属性在注释中指定的方式,没有配置其他功能。
    • 跟进:在响应 XSD 中,我定义了一个复杂类型,但在 JSON 响应中,该属性以空字符串的形式出现。是否有配置功能来处理这个问题,或者我应该修改我的 XSD?
    • 自从我使用 XSD 以来已经有一段时间了,所以我不太确定你在说什么。不过要注意的一件事是,Jackson 不支持所有 JAXB 注释。见this
    【解决方案3】:

    如评论中所述,将@JsonProperty 添加到字段中。

    使用 Jackson 2.7.0 对我来说效果很好:

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = { "trackRequest" })
    @XmlRootElement(name = "Request")
    class Request {
    
        @XmlElement(name = "TrackRequest")
        @JsonProperty("TrackRequest")
        private TrackRequest trackRequest;
    
        public Request() {
        }
        public Request(TrackRequest trackRequest) {
            this.trackRequest = trackRequest;
        }
    }
    
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = { "inquiryNumber" })
    class TrackRequest {
    
        @XmlElement(name = "InquiryNumber")
        @JsonProperty("InquiryNumber")
        private String inquiryNumber;
    
        public TrackRequest() {
        }
        public TrackRequest(String inquiryNumber) {
            this.inquiryNumber = inquiryNumber;
        }
    }
    

    测试

    Request upsRequest = new Request(new TrackRequest("1Z12345E6205277936"));
    
    Marshaller marshaller = JAXBContext.newInstance(Request.class).createMarshaller();
    marshaller.setProperty("jaxb.formatted.output", Boolean.TRUE);
    marshaller.marshal(upsRequest, System.out);
    
    ObjectMapper mapper = new ObjectMapper();
    mapper.enable(SerializationFeature.INDENT_OUTPUT);
    mapper.writeValue(System.out, upsRequest);
    

    输出

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Request>
        <TrackRequest>
            <InquiryNumber>1Z12345E6205277936</InquiryNumber>
        </TrackRequest>
    </Request>
    
    {
      "TrackRequest" : {
        "InquiryNumber" : "1Z12345E6205277936"
      }
    }
    

    XML 和 JSON 输出都使用PascalCase

    【讨论】:

    • 这行得通,我确实通过此注释获得了所需的输出,但是我更喜欢坚持使用我熟悉的 JAXB 注释。
    猜你喜欢
    • 2016-11-16
    • 1970-01-01
    • 2015-12-05
    • 2016-04-19
    • 2016-01-16
    • 2020-02-12
    • 1970-01-01
    • 1970-01-01
    • 2016-09-11
    相关资源
    最近更新 更多