Java 为什么我的DateTime反序列化程序正在截断DateTime';s分/秒/毫秒?

Java 为什么我的DateTime反序列化程序正在截断DateTime';s分/秒/毫秒?,java,json,datetime,gson,jodatime,Java,Json,Datetime,Gson,Jodatime,我有一个类,反序列化JSON元素 public class DateTimeConverter implements JsonSerializer<DateTime>, JsonDeserializer<DateTime> { private static final DateTimeFormatter DATE_FORMAT = ISODateTimeFormat.dateHourMinuteSecondMillis(); @Override p

我有一个类,
反序列化
JSON
元素

public class DateTimeConverter implements JsonSerializer<DateTime>, JsonDeserializer<DateTime>
{
    private static final DateTimeFormatter DATE_FORMAT = ISODateTimeFormat.dateHourMinuteSecondMillis();
    @Override
    public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context)
    {
        final DateTimeFormatter fmt = ISODateTimeFormat.dateHourMinuteSecondMillis();
        return new JsonPrimitive(fmt.print(src));
    }


    @Override
    public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException
    {
        final String dateAsString = json.getAsString();
        System.out.println(dateAsString);
        if (json.isJsonNull() || dateAsString.length()==0)
        {
            return null;
        }
        else
        {
            return DATE_FORMAT.parseDateTime(json.getAsString());
        }
    }
}
我收到:

2015-07-29T11
System.out.println(dateAsString)为什么它要截断我的输入

我认为我的问题在我的测试课上:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import org.joda.time.DateTime;
import org.junit.Test;

import java.lang.reflect.Type;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
 * Tests {@link DateTimeConverter}.
 */
public class DateTimeConverterTest {
    String testTime = "2015-07-29T11:00:00.001Z";

    @Test
    public void testDateTimeConverter() throws Exception {
        final Gson gson = initCustomGSON();
        Type DateTimeType = new TypeToken<DateTime>() {
        }.getType();

        System.out.println(testTime);
        DateTimeConverter timeConverter = new DateTimeConverter();
        DateTime m = (gson.fromJson(testTime, DateTimeType));

        assertThat("11", is(m.hourOfDay().getAsText()));
    }

    public Gson initCustomGSON() {
        final GsonBuilder builder = new GsonBuilder();
        JodaTimeConverters converter = new JodaTimeConverters();
        converter.registerAll(builder);
        return builder.create();
    }

}
我构建了一个
DateTime
对象,用于谷歌的Gson。但是,我认为
DateTimeType
的默认构造函数不支持分/秒/毫秒。有没有办法扩展
DateTimeType
来支持它

这是我的测试课:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import org.joda.time.DateTime;
import org.junit.Test;

import java.lang.reflect.Type;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
 * Tests {@link DateTimeConverter}.
 */
public class DateTimeConverterTest {
    String testTime = "2015-07-29T11:00:00.001Z";

    @Test
    public void testDateTimeConverter() throws Exception {
        final Gson gson = initCustomGSON();
        Type DateTimeType = new TypeToken<DateTime>() {
        }.getType();

        System.out.println(testTime);
        DateTimeConverter timeConverter = new DateTimeConverter();
        DateTime m = (gson.fromJson(testTime, DateTimeType));

        assertThat("11", is(m.hourOfDay().getAsText()));
    }

    public Gson initCustomGSON() {
        final GsonBuilder builder = new GsonBuilder();
        JodaTimeConverters converter = new JodaTimeConverters();
        converter.registerAll(builder);
        return builder.create();
    }

}
import com.google.gson.gson;
导入com.google.gson.GsonBuilder;
导入com.google.gson.reflect.TypeToken;
导入org.joda.time.DateTime;
导入org.junit.Test;
导入java.lang.reflect.Type;
导入静态org.hamcrest.CoreMatchers.is;
导入静态org.hamcrest.matcherasert.assertThat;
/**
*测试{@link DateTimeConverter}。
*/
公共类DateTimeConverterTest{
字符串testTime=“2015-07-29T11:00:00.001Z”;
@试验
public void testDateTimeConverter()引发异常{
final Gson Gson=initCustomGSON();
类型DateTimeType=新类型令牌(){
}.getType();
System.out.println(测试时间);
DateTimeConverter timeConverter=新的DateTimeConverter();
DateTime m=(gson.fromJson(testTime,DateTimeType));
资产(“11”,是(m.hourOfDay().getAsText());
}
公共Gson initCustomGSON(){
最终GsonBuilder=新的GsonBuilder();
JodaTimeConverters converter=新的JodaTimeConverters();
转换器注册表(生成器);
返回builder.create();
}
}

此代码存在一些问题

  • 第一个问题是
    是Json中的运算符。您正在解释一个未转义的
    字符串,其中包含
    ,因此Gson将其解释为
    。您的测试字符串需要用引号括住整个文本日期,以防止这种情况发生,例如

    String testTime = "\"2015-07-29T11:00:00.001Z\"";
    
  • 您在代码中使用了。但是,它的格式模式是
    yyyy-MM-dd'T'HH:MM:ss.SSS
    ,如您所见,它不包括时区。您要使用的模式是
  • yyyy-MM-dd'HH:MM:ss.SSSZZ
    ,它确实有一个时区

    private static final DateTimeFormatter DATE_FORMAT = ISODateTimeFormat.dateTime();
    
  • 完成这两项更改后,
    DateTime
    对象最终正确创建。。。但它将在您的本地时区创建,而不是UTC(它将正确调整您所在时区的时间。您可以通过执行以下操作轻松地将其切换回UTC):

    DateTime m = ((DateTime) (gson.fromJson(testTime, DateTimeType))).withZone(DateTimeZone.UTC);
    
  • 一旦您进行了这三项更改,您的测试将通过。但是:我强烈建议不要使用
    JsonSerializer
    jsondeselineizer
    ,它们已被弃用,而支持使用其流式API

    新的应用程序应该更喜欢
    TypeAdapter
    ,其流式API比此接口的树API更高效

    我知道《用户指南》提供了如何使用
    JsonSerializer
    /
    JsonDeserializer
    API执行此操作的代码,但这只是因为他们还没有更新它

    简单来说就是这样:

    public class DateTimeAdapter extends TypeAdapter<DateTime> {
      private static final DateTimeFormatter FORMAT = ISODateTimeFormat.dateTime();
    
      public DateTime read(JsonReader reader) throws IOException {
        if (reader.peek() == JsonToken.NULL) {
          reader.nextNull();
          return null;
        }
        String dateString = reader.nextString();
        if(dateString.length() == 0) return null;
        return FORMAT.parseDateTime(dateString);
      }
    
      public void write(JsonWriter writer, DateTime value) throws IOException {
        if (value == null) {
          writer.nullValue();
          return;
        }
        writer.value(FORMAT.print(value));
      }
    }
    
    公共类DateTimeAdapter扩展了TypeAdapter{
    私有静态最终DateTimeFormatter FORMAT=ISODateTimeFormat.dateTime();
    公共日期时间读取(JsonReader)引发IOException{
    if(reader.peek()==JsonToken.NULL){
    reader.nextNull();
    返回null;
    }
    String dateString=reader.nextString();
    if(dateString.length()==0)返回null;
    返回格式.parseDateTime(日期字符串);
    }
    public void write(JsonWriter,DateTime值)引发IOException{
    如果(值==null){
    writer.nullValue();
    返回;
    }
    writer.value(FORMAT.print(value));
    }
    }
    
    我对GSON了解不多,但也许像这样的库可以帮助你?哈哈哈,这就是我的反序列化程序的基础!:)让我们一起来吧。谢谢,我明天早上回到办公室后会尝试你的建议:)。所以这种方法奏效了(最初)。但我有一个问题是,如果服务器返回的是未替换字符串,那么我是否可以将其修改为可接受的?一个示例数据返回是Json数组:
    {“roomId”:“jYNpbH15Vb”,“startTime”:“2015-07-29T11:00:00.000-0500”,“endTime”:“2015-07-29T12:00:00.000-0500”,“meetingName”:“OSQ要求”,“contactName”:“姓名”,“createdAt:“2015-07-29T07:23:47.269-0500”,“updatedAt:“2015-07-29T07:23:47.269-0500”,“objectId:“DaxfYVHkwf”}
    正确,但我说的是,当我返回这些值时,反序列化时程序仍会崩溃。我想知道是否出于某种原因,您所说的困惑是它崩溃的原因?