Java 8 如何使用com.fasterxml.jackson.databind.ObjectMapper将json字符串解析为相应的JAXB对象

Java 8 如何使用com.fasterxml.jackson.databind.ObjectMapper将json字符串解析为相应的JAXB对象,java-8,xsd,jaxb,jackson-databind,Java 8,Xsd,Jaxb,Jackson Databind,背景: - - - [INFO] --- exec-maven-plugin:1.2.1:exec (default-cli) @ thingtst --- com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class javax.xml.bind.JAXBElement<javax.xml.datatype.XMLGregorianCal

背景:

-
-
-
[INFO] --- exec-maven-plugin:1.2.1:exec (default-cli) @ thingtst ---
com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class javax.xml.bind.JAXBElement<javax.xml.datatype.XMLGregorianCalendar>] from String value ('2017-10-18T00:00:00.000-04:00'); no single-String constructor/factory method
 at [Source: {"Thing":[{"ThingNbr":"33333333","ThingDt":"2017-10-18T00:00:00.000-04:00"}]}; line: 1, column: 33] (through reference chain: aaa.bbb.ccc.generated.ThingList["Thing"]->java.util.ArrayList[0]->aaa.bbb.ccc.generated.ThingType["ThingDt"])
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:878)
    at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:281)
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:284)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1176)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:145)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:136)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:217)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:25)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2726)
    at aaa.bbb.ccc.jar.Thingtst.main(Thingtst.java:18)    -
-
-
(注意,date元素——即带有“nillable”属性的元素——似乎导致了“com.fasterxml.jackson.databind.JsonMappingException”)

问题:

-
-
-
[INFO] --- exec-maven-plugin:1.2.1:exec (default-cli) @ thingtst ---
com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class javax.xml.bind.JAXBElement<javax.xml.datatype.XMLGregorianCalendar>] from String value ('2017-10-18T00:00:00.000-04:00'); no single-String constructor/factory method
 at [Source: {"Thing":[{"ThingNbr":"33333333","ThingDt":"2017-10-18T00:00:00.000-04:00"}]}; line: 1, column: 33] (through reference chain: aaa.bbb.ccc.generated.ThingList["Thing"]->java.util.ArrayList[0]->aaa.bbb.ccc.generated.ThingType["ThingDt"])
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:878)
    at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:281)
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:284)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1176)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:145)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:136)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:217)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:25)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2726)
    at aaa.bbb.ccc.jar.Thingtst.main(Thingtst.java:18)    -
-
-
如何使用com.fasterxml.jackson.databind.ObjectMapper将json字符串解析为相应的JAXB对象形式(参见下面的示例代码)

非常简单的模式如下所示(注意带有“nillable”属性的date元素):

* * * *列表中允许以下类型的对象 *{@link ThingType} * * */ 公共列表getThing(){ if(thing==null){ thing=newarraylist(); } 归还这个东西; } } ThingType.java

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.6.3</version>
</dependency>
Thingtst.java现在看起来像这样:

JavaTimeModule module = new JavaTimeModule();
om.registerModule(module);
包aaa.bbb.ccc.jar;
导入aaa.bbb.ccc.生成。*;
导入com.fasterxml.jackson.databind.JsonMappingException;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入com.fasterxml.jackson.datatype.jsr310.*;
导入java.io.IOException;
公共类事物{
公共静态void main(字符串[]args)引发JsonMappingException{
ObjectMapper om=新的ObjectMapper();
om.setPropertyNamegstrategy(新的PreservePropertyNameStrategy());//在jackson 2.6.3:PropertyNamegstrategy.UPPER_中不可用);
registerModule(新的JavaTimeModule());
字符串jsonString=“{\'Thing\”:[{\'ThingNbr\”:\'33333333\,\'ThingDt\“:\'2017-10-18T00:00:00.000-04:00\”}”;
试试{

ThingList tl=om.readValue(jsonString,ThingList.class);//您可以尝试以下更改

Jax B的变化

1.创建一个日期时间适配器,将xs:date类型映射到java 8时间类

<dependency>
      <groupId>com.fasterxml.jackson.module</groupId>
      <artifactId>jackson-modules-java8</artifactId>
<dependency>
2.添加一个xjb文件(binding.xjb)来控制类的生成,并将其放在src/xjb下

注册适配器以在生成类时将xsd日期映射到ZonedDateTime

卸下JAXBElement包装

2.在pom中添加java时间模块


com.fasterxml.jackson.module
jackson-modules-java8

谢谢,Veeram。-我很快会尝试一下您的更改,然后回复您。:-)使用非常小的MOD(例如,依赖项名称和文件夹位置),效果很好!谢谢,Veeram!
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>aaa.bbb.ccc</groupId>
    <artifactId>thingtst</artifactId>
    <version>1</version>
    <packaging>jar</packaging>
    <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
    <dependency>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-core</artifactId>
        <version>2.17.0</version>
        <scope>provided</scope>
    </dependency>     
    <dependency>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-jackson</artifactId>
        <version>2.17.0</version>
        <scope>provided</scope>               
    </dependency>      
    <dependency>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-cxf</artifactId>
        <version>2.17.0</version>
        <scope>provided</scope>              
    </dependency> 
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.6.3</version>
    </dependency>             

    </dependencies>

    <build>
    <finalName>${project.artifactId}-${project.version}</finalName>

    <resources>
        <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
        </resource>
    </resources>

    <plugins>

        <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
            <showDeprecation>true</showDeprecation>
        </configuration>
        </plugin> 

        <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>jaxb2-maven-plugin</artifactId>
        <version>2.3</version>
        <executions>
            <execution>
            <id>xjc</id>
            <goals>
                <goal>xjc</goal>
            </goals>
            </execution>
        </executions>        
        <configuration>
            <sources>
            <source>src/main/resources/xsd/Thing.xsd</source>
            </sources>
            <packageName>aaa.bbb.ccc.generated</packageName>                    
            <verbose default-value="false">${xjc.verbose}</verbose>
        </configuration>                
        </plugin>              

    </plugins>
    </build>
</project>
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.6.3</version>
</dependency>
<jxb:bindings version="2.0" 
          xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
          xmlns:xs="http://www.w3.org/2001/XMLSchema" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <jxb:bindings schemaLocation="../resources/xsd/Thing.xsd">
    <jxb:globalBindings generateElementProperty="false">
        <jxb:javaType 
        name="java.time.ZonedDateTime" 
        xmlType="xs:date" 
        parseMethod="aaa.bbb.ccc.jar.DateTimeAdapter.parseDateTime" 
        printMethod="aaa.bbb.ccc.jar.DateTimeAdapter.formatDateTime" />
    </jxb:globalBindings>
    </jxb:bindings>
</jxb:bindings>
package aaa.bbb.ccc.jar;

import java.time.ZonedDateTime;

public class DateTimeAdapter {
    public static String formatDateTime(ZonedDateTime dateTime) {
    return dateTime.toString();
    }
    public static ZonedDateTime parseDateTime(String dateTime) {
    return ZonedDateTime.parse(dateTime);
    }
}
package aaa.bbb.ccc.jar;

import aaa.bbb.ccc.generated.*;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.*;
import java.io.IOException;

public class Thingtst {

    public static void main(String[] args) throws JsonMappingException {

    ObjectMapper om = new ObjectMapper();
    om.setPropertyNamingStrategy(new PreservePropertyNameStrategy()); //not available in jackson 2.6.3:  PropertyNamingStrategy.UPPER_CASE);  
    om.registerModule(new JavaTimeModule());          

    String jsonString = "{\"Thing\":[{\"ThingNbr\":\"33333333\",\"ThingDt\":\"2017-10-18T00:00:00.000-04:00\"}]}";

    try {                  
        ThingList tl = om.readValue(jsonString, ThingList.class);  //<== causes JsonMappingException!!!
        System.out.println("ThingNbr=" + tl.getThing().get(0).getThingNbr() + "...ThingDt=" + tl.getThing().get(0).getThingDt());            
    } catch (IOException e) {
        e.printStackTrace();
    }
    }
}
package aaa.bbb.ccc.jar;
import java.time.ZonedDateTime;

public class DateTimeAdapter {

 public static  String formatDateTime(ZonedDateTime dateTime) {
     return dateTime.toString();
 }

 public static ZonedDateTime parseDateTime(String dateTime) {
     return ZonedDateTime.parse(dateTime);
 }
}
<jxb:bindings version="2.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <jxb:bindings schemaLocation="../resources/Thing.xsd">
        <jxb:globalBindings generateElementProperty="false">
          <jxb:javaType name="java.time.ZonedDateTime" xmlType="xs:date" parseMethod="aaa.bbb.ccc.jar.DateTimeAdapter.parseDateTime" printMethod="aaa.bbb.ccc.jar.DateTimeAdapter.formatDateTime" />
        </jxb:globalBindings>
    </jxb:bindings>
</jxb:bindings>
JavaTimeModule module = new JavaTimeModule();
om.registerModule(module);
<dependency>
      <groupId>com.fasterxml.jackson.module</groupId>
      <artifactId>jackson-modules-java8</artifactId>
<dependency>