简体   繁体   English

使用JAXB解组日期和货币属性时出现意外值

[英]Unexpected values when unmarshalling Date and Currency attributes using JAXB

I am trying to umarshall xml response to java pojo. 我正在尝试对Java pojo进行umarshall xml响应。 Having issues with date and currency values while unmarshalling using jaxb 使用jaxb解组时出现日期和货币值问题

Results of unmarshalling, the currency field value not getting mapped(null) and date field is mapped to some numbers(like 1503979200000) 解组结果,货币字段值未映射(空)和日期字段被映射到某些数字(例如1503979200000)

Could someone please let me know where I am going wrong? 有人可以让我知道我要去哪里了吗? Thanks in advance for your help. 在此先感谢您的帮助。

Below is my code: unmarshall code: JAXBContext jc = JAXBContext.newInstance(Item.class); 下面是我的代码:解组代码:JAXBContext jc = JAXBContext.newInstance(Item.class); Unmarshaller um = jc.createUnmarshaller(); Unmarshaller um = jc.createUnmarshaller(); Item output = (Item)um.unmarshal(soapMessage.getSOAPBody().extractContentAsDocument()); 项目输出=(Item)um.unmarshal(soapMessage.getSOAPBody()。extractContentAsDocument());

Pojo: Pojo:

@XmlRootElement( name = "item" )
@XmlAccessorType(XmlAccessType.FIELD)  

public class Item{

 @XmlElement( name = "bl" )
 @XmlJavaTypeAdapter(DateTimeAdapter.class)
 private Date docDate;

 @XmlElement( name = "sd" )
 @XmlJavaTypeAdapter(DateTimeAdapter.class)
 private Date dueDate;

 @XmlElement( name = "bu" )
 @XmlJavaTypeAdapter(DateTimeAdapter.class)
 private Date postingDate;

 @XmlElement( name = "wr" )
 @XmlJavaTypeAdapter(CurrencyAdapter.class)
 private Currency amount;

...

} }

Date value in XML is in the format of yyyy-MM-dd XML中的日期值格式为yyyy-MM-dd

Result after unmarshalling: amount = null docDate=1503979200000 dueDate=1503979200000 postingDate=1503979200000 解组后的结果:数量= null docDate = 1503979200000 dueDate = 1503979200000 postedDate = 1503979200000

tl;dr tl; dr

  • Feature, not a bug. 功能,不是错误。
  • Your number 1_503_979_200_000L is a count of milliseconds from 1970-01-01T00:00:00Z. 您的数字1_503_979_200_000L是从1970-01-01T00:00:00Z开始的毫秒数。

Tips: 提示:

  • Use java.time classes instead of legacy date-time classes. 使用java.time类而不是旧的日期时间类。
  • Use ISO 8601 formats when serializing date-time values to text. 将日期时间值序列化为文本时,请使用ISO 8601格式。

Count-from-epoch 从时代开始计数

Your java.util.Date object is being serialized as a count of milliseconds since the epoch reference moment of first moment of 1970 in UTC, 1970-01-01T00:00:00Z. 您的java.util.Date对象被序列化为自1970年1月的UTC 1970年第一时刻的纪元参考时刻以来的毫秒数(1970-01-01T00:00:00Z)。 Sometimes called Unix Time, or POSIX Time . 有时称为Unix Time或POSIX Time

java.time java.time

The java.util.Date class you are using is one of the terrible old date-time classes bundled with the earliest versions of Java. 您正在使用的java.util.Date类是与最早的Java版本捆绑在一起的可怕的旧日期时间类之一。 Do not use these classes! 不要使用这些类! Years ago they were supplanted by the java.time classes built into Java 8 and later. 多年前,它们被Java 8及更高版本中内置的java.time类所取代。

Specifically, Date was replaced by Instant . 具体来说, Date替换为Instant Both represent a moment in UTC , but Instant resolves to the finer level of nanoseconds rather than milliseconds. 两者都表示UTC中的一个时刻,但Instant解析为纳秒级的更好级别,而不是毫秒级。

long input = 1_503_979_200_000L;
Instant instant = Instant.ofEpochMilli( input  );

instant.toString(): 2017-08-29T04:00:00Z Instant.toString():2017-08-29T04:00:00Z

According to the Answer on my Question , JAXB has not yet been updated for java.time . 根据对我的问题 的答案 ,JAXB尚未针对java.time更新。 However, adapters are available, such as this one . 但是,有可用的适配器,例如适配器。

ISO 8601 ISO 8601

The ISO 8061 standard defines practical useful formats for serializing date-time values as text. ISO 8061标准定义了将日期时间值序列化为文本的实用格式。 They are easy to parse by machine. 它们很容易用机器解析。 They are easy to read by humans across cultures. 跨文化的人类很容易阅读它们。

The java.time classes use these formats by default when parsing/generating strings. 解析/生成字符串时, java.time类默认使用这些格式。

Example app 示例应用

Here is a simple little example app to demonstrate how to use the java.time class Instant . 这是一个简单的小示例应用程序,用于演示如何使用java.timeInstant

We added the JAXB adapters for Java 8 Date and Time API (JSR-310) types library via Maven. 我们通过Maven添加了Java 8 Date and Time API(JSR-310)类型库的JAXB适配器 We need this adapter for Instant as JAXB has not yet been updated for java.time types. 我们需要此适配器用于Instant因为JAXB尚未针对java.time类型进行更新。 Hopefully that update can happen if we see swifter development with the Jakarta EE organization. 如果我们看到Jakarta EE组织的迅速发展,希望能够进行更新。

<dependency>
    <groupId>com.migesok</groupId>
    <artifactId>jaxb-java-time-adapters</artifactId>
    <version>1.1.3</version>
</dependency>

First, our simple little business-object class Event with a pair of properties, when and description . 首先,我们的简单业务对象类Event具有两个属性whendescription

package com.basilbourque.example;

import com.migesok.jaxb.adapter.javatime.InstantXmlAdapter;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.time.Instant;

public class Event {

    private Instant when;
    private String description;

    // ---------------|  Constructors  |-------------------------

    public Event ( Instant when , String description ) {
        this.when = when;
        this.description = description;
    }

    // ---------------|  Accessors  |-------------------------

    @XmlJavaTypeAdapter ( InstantXmlAdapter.class )
    public Instant getWhen () {
        return when;
    }

    public void setWhen ( Instant when ) {
        this.when = when;
    }

    public String getDescription () {
        return description;
    }

    public void setDescription ( String description ) {
        this.description = description;
    }

    // ---------------|  Object  |-------------------------

    @Override
    public String toString () {
        return "Event{ " +
                "when=" + when +
                ", description='" + description + '\'' +
                " }";
    }
}

Instantiate a business object. 实例化业务对象。

Event e = new Event( Instant.now() , "Devoxx" );
System.out.println("e.toString(): " + e);
System.out.println(""); // blank line.

e.toString(): Event{ when=2018-07-31T04:03:43.113356Z, description='Devoxx' } e.toString():事件{当= 2018-07-31T04:03:43.113356Z,description ='Devoxx'}

Run our JAXB code. 运行我们的JAXB代码。

try {
    JAXBContext jc = JAXBContext.newInstance( Event.class );
    Marshaller marshaller = jc.createMarshaller();
    marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT , true );
    JAXBElement< Event > jaxbElement = new JAXBElement< Event >( new QName( "event" ) , Event.class , e );
    marshaller.marshal( jaxbElement , System.out );
} catch ( JAXBException e1 ) {
    e1.printStackTrace();
}

Results: 结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<event>
    <description>Devoxx</description>
    <when>2018-07-31T04:03:43.113356Z</when>
</event>

We see the standard ISO 8601 format was used in the XML, 2018-07-31T04:03:43.113356Z . 我们看到XML, 2018-07-31T04:03:43.113356Z使用了标准的ISO 8601格式。 The Z on the end means UTC , and is pronounced Zulu . 末端的Z表示UTC ,发音为Zulu

Much more readable than 1503979200000 ! 1503979200000更具可读性! 😀 😀


About java.time 关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat . 这些类取代了麻烦的旧的旧式日期时间类,例如java.util.DateCalendarSimpleDateFormat

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes. 现在处于维护模式Joda-Time项目建议迁移到java.time类。

To learn more, see the Oracle Tutorial . 要了解更多信息,请参见Oracle教程 And search Stack Overflow for many examples and explanations. 并在Stack Overflow中搜索许多示例和说明。 Specification is JSR 310 . 规格为JSR 310

You may exchange java.time objects directly with your database. 您可以直接与数据库交换java.time对象。 Use a JDBC driver compliant with JDBC 4.2 or later. 使用与JDBC 4.2或更高版本兼容的JDBC驱动程序 No need for strings, no need for java.sql.* classes. 不需要字符串,不需要java.sql.*类。

Where to obtain the java.time classes? 在哪里获取java.time类?

The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time. 该项目为将来可能在java.time中添加内容提供了一个试验场。 You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more . 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM