【问题标题】:Jackson UnrecognizedProperyException when parsing XML解析 XML 时的 Jackson UnrecognizedProperyException
【发布时间】:2021-08-09 08:30:30
【问题描述】:

我正在尝试解析一个 XML,在其中我使用 xsd 文件中的 maven-jaxb2-plugin 生成 DTO。但是我得到了这个异常,不知道为什么,一切似乎都很好。

Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Publish_Date" (class com.compnay.package.SdnList$PublshInformation), not marked as ignorable (2 known properties: "publishDate", "recordCount"])
 at [Source: (PushbackInputStream); line: 4, column: 44] (through reference chain: com.compnay.package.SdnList["publshInformation"]->com.compnay.package.domain.SdnList$PublshInformation["Publish_Date"])

相关xsd的Jaxb执行

<execution>
  <id>tds</id>
  <goals>
    <goal>generate</goal>
  </goals>
  <configuration>
    <schemas>
      <schema>                              
        <url>xsd url</url>
      </schema>
  </schemas>                     
  <generatePackage>com.company.domain</generatePackage>
  <generateDirectory>${project.basedir}/domain/src/main/java</generateDirectory>
  <episode>false</episode>
  </configuration>
</execution>

我收到错误的部分 XML 文件。

<publshInformation>
  <Publish_Date>08/06/2021</Publish_Date>
  <Record_Count>9030</Record_Count>
</publshInformation>

休息模板配置

JacksonXmlModule module = new JacksonXmlModule();
module.setDefaultUseWrapper(false);

final XmlMapper xmlMapper = new XmlMapper(module);
xmlMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
// xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // Works when this is on

final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(xmlMapper);
        converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_XML));

        return new RestTemplateBuilder()
                .setReadTimeout(Duration.ofMillis(readTimeout))
                .setConnectTimeout(Duration.ofMillis(connectTimeout))
                .messageConverters(converter)
                .build();

生成的 DTO 的一部分

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "publshInformation",
    "sdnEntry"
})
@XmlRootElement(name = "sdnList")
public class SdnList {

    @XmlElement(required = true)
    protected SdnList.PublshInformation publshInformation;
    @XmlElement(required = true)
    protected List<SdnList.SdnEntry> sdnEntry;

    ........

    /**
     * <p>Java class for anonymous complex type.
     * 
     * <p>The following schema fragment specifies the expected content contained within this class.
     * 
     * <pre>
     * &lt;complexType&gt;
     *   &lt;complexContent&gt;
     *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt;
     *       &lt;sequence&gt;
     *         &lt;element name="Publish_Date" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/&gt;
     *         &lt;element name="Record_Count" type="{http://www.w3.org/2001/XMLSchema}int" minOccurs="0"/&gt;
     *       &lt;/sequence&gt;
     *     &lt;/restriction&gt;
     *   &lt;/complexContent&gt;
     * &lt;/complexType&gt;
     * </pre>
     * 
     * 
     */
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "publishDate",
        "recordCount"
    })
    public static class PublshInformation {

        @XmlElement(name = "Publish_Date")
        protected String publishDate;
        @XmlElement(name = "Record_Count")
        protected Integer recordCount;
        ........
    }
}

我可以使用xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) 使其工作,但我不想丢失其他数据。谁能帮我弄清楚为什么我会得到 unrecognizedPropertyException?我将不胜感激。

【问题讨论】:

    标签: jackson jaxb jackson-databind jaxb2-maven-plugin


    【解决方案1】:

    我猜您在derealization 之前正在做某事,这会使您的输入流为空,因此您会收到此错误。我使用了提供的 XML,似乎对我来说工作正常:

    XML:

    <publshInformation>
        <Publish_Date>08/06/2021</Publish_Date>
        <Record_Count>9030</Record_Count>
    </publshInformation>
    

    PublshInformation.class:

    @XmlRootElement(name = "publshInformation")
    @Data
    @XmlAccessorType(XmlAccessType.FIELD)
    public class PublshInformation {
    
        @XmlElement(name = "Publish_Date")
        private String Publish_Date;
    
        @XmlElement(name = "Record_Count")
        private Integer recordCount;
    
    }
    

    PublishMain.class:

    public class PublishMain {
        public static void main(String[] args) throws JAXBException, XMLStreamException, IOException {
            final InputStream inputStream = Unmarshalling.class.getClassLoader().getResourceAsStream("publish.xml");
            final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
    /*        final Unmarshaller unmarshaller = JAXBContext.newInstance(PublshInformation.class).createUnmarshaller();
            final PublshInformation publshInformation = unmarshaller.unmarshal(xmlStreamReader, PublshInformation.class).getValue();
            System.out.println(publshInformation.toString());
    
            Marshaller marshaller = JAXBContext.newInstance(PublshInformation.class).createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            marshaller.marshal(publshInformation, System.out);*/
    
            System.out.println(inputStream);
            final XmlMapper xmlMapper = new XmlMapper();
            xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            PublshInformation jacksonPublish = xmlMapper.readValue(xmlStreamReader, PublshInformation.class);
            System.out.println(jacksonPublish);
    
            xmlMapper.writerWithDefaultPrettyPrinter().writeValue(System.out, jacksonPublish);
    
        }
    }
    

    这将产生结果:

    java.io.BufferedInputStream@73a28541
    PublshInformation(Publish_Date=null, recordCount=null)
    <PublshInformation>
      <recordCount/>
      <publish_Date/>
    </PublshInformation>
    

    即使使用纯 JAXB,上面的代码也可以工作。如果您取消注释,那么它将使用 JAXB 来完成。我用的是最新的jackson-dataformat-xml 2.12.4

    1. 将您的字段设为私有。
    2. 使用最新版本的 Jackson
    3. 确保您的输入未被使用,之前可能会变为空。

    我相信这应该可行。

    【讨论】:

    • 感谢您的意见。我正在使用杰克逊 2.10。对于这些字段,我无法将它们设为私有,因为它们是自动生成的,但我没有使用输入。我只打电话给restTemplate.getForEntity(this.url, SdnList.class);。调试时,在类BeanPropertyMap 和方法SettableBeanProperty find(String key) 中,键Publish_date 与recordCount 匹配,这是错误的。这可能是一个错误。
    • 如果是这种情况,可能会在Jackson Github 中提出问题请求,他们可以提供更好的解释和一些临时解决方法。他们通常反应很快。
    • 我认为它与杰克逊无关。 jax2b-plugin 正在生成糟糕的 DTO 我相信当我自己编写 DTO 时它会起作用。
    • 很高兴知道你能弄明白
    猜你喜欢
    • 2021-01-25
    • 2019-09-16
    • 1970-01-01
    • 2018-11-07
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 2017-04-16
    • 2023-03-13
    相关资源
    最近更新 更多