【问题标题】:Java JSONParser distinguish type of the objectJava JSONParser 区分对象的类型
【发布时间】:2017-09-06 08:25:54
【问题描述】:

我有一个Date 序列化程序,它在反序列化Date 对象时会添加时区,但我注意到一些Date 对象被转换为String 而不是长值,我得到一个StringDate

所以当我尝试:

Long dateValue = jsonParser.getLongValue();
Date date = new Date(dateValue);

它会抛出格式异常,所以当我得到 **String** 形状的Date 时,我需要这样做

String dateString = jsonParser.getText();

dateString 的值为"2017-09-06"

有没有办法知道 jsonParser 对象是什么类型?因为instanceof 在这种情况下不起作用。

【问题讨论】:

  • dateString 的值是多少?
  • 是字符串“2017-09-06”

标签: java json date serialization deserialization


【解决方案1】:

如果 instanceof 不起作用,您可以使用将 String 转换为 Long 这可能会起作用。

Long.valueOf(String s).longValue();

【讨论】:

  • 这无济于事,因为抛出异常 jsonParser.getLongValue()
【解决方案2】:

如果String 的值为2017-09-06,这就是您无法将其作为long 获取的原因。要从此String 中获取Date,您需要使用SimpleDateFormat

String dateString = "2017-09-06";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(dateString);

唯一的问题是Date 不完全是日期(具有定义的日/月/年)。它有no format and no timezone information,它只有自1970-01-01T00:00Z(1970 年 1 月 1 日st 午夜 UTC)以来的毫秒数 - 也称为“unix 时间戳” 、“毫值”和many other names

使用上面的SimpleDateFormat 将创建一个具有指定日期的Date(2017 年 9 月 6 日th)。由于没有指定时间,它会默认为午夜,它也会使用 JVM 默认时区。因此,这可以根据 JVM 中设置的时区返回不同的日期(不同的毫秒值)。

如果你想使用特定的时区,只需在格式化程序中设置:

sdf.setTimeZone(TimeZone.getTimeZone("Europe/London"));

我使用了Europe/London,但您可以使用您想要的任何其他时区。您可以致电TimeZone.getAvailableIDs() 获取所有可用区域的列表(并选择最适合您的情况)。

API 使用IANA timezones names(始终采用Region/City 格式,如America/Sao_PauloEurope/Berlin)。 避免使用三个字母的缩写(如CSTPST),因为它们是ambiguous and not standard


Java 新日期/时间 API

旧的类(DateCalendarSimpleDateFormat)有 lots of problemsdesign issues,它们正在被新的 API 取代。

如果您使用的是 Java 8,请考虑使用 new java.time API。更简单,less bugged and less error-prone than the old APIs

如果您使用的是 Java ,则可以使用 ThreeTen Backport,它是 Java 8 新日期/时间类的出色向后移植。对于Android,您还需要ThreeTenABP(更多关于如何使用它here)。

下面的代码适用于两者。 唯一的区别是包名(在 Java 8 中是 java.time,而在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp),但类和方法 names 是相同的。

要解析这个String,你可以使用LocalDate

// get a LocalDate from 2017-09-06
LocalDate dt = LocalDate.parse(dateString);

然后您可以将其转换为Date。在下面的代码中,我模拟了 SimpleDateFormat 所做的事情:将时间设置为 JVM 默认时区的午夜。在 Java 8 中,您可以使用 Date.from 方法,而在 Java 7 中,ThreeTen Backport API 具有 org.threeten.bp.DateTimeUtils 类:

// convert to java.util.Date (Java 8)
Date d = Date.from(dt.atStartOfDay(ZoneId.systemDefault()).toInstant());
// convert to java.util.Date (Java 7 ThreeTen Backport)
Date d = DateTimeUtils.toDate(dt.atStartOfDay(ZoneId.systemDefault()).toInstant());

只是提醒使用默认时区可能会很棘手,因为这是can be changed without notice, even at runtime,所以最好始终明确说明您使用的是哪个时区。

您可以使用ZoneId.of("Europe/London") 指定您想要的时区 - 将Europe/London 更改为您想要的时区。要获取所有区域的列表,请使用ZoneId.getAvailableZoneIds()


不在问题范围内,但您也可以使用 API(例如 Jackson)来处理 JSON - 它具有与大多数类型(包括日期)的内置转换。在 标签中,您会发现很多有关日期操作的相关问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 1970-01-01
    • 2019-08-10
    相关资源
    最近更新 更多