Jackson序列化Java Date至Unity JsonUtility解析失败,咨询可行方案及性能影响
问题描述
我最近在做Spring Boot后端和Unity前端的对接时,碰到了一个日期解析的坑:后端用Jackson序列化的Date字段,前端用Unity的JsonUtility始终解析成1970年的默认空日期。具体情况如下:
- 后端返回的JSON日期格式:
{"aDate": "2018-05-18T22:35:47.760+0000"} - 前端解析后,
dateObject.aDate总是显示1970-01-01
我现在有两个疑问:
- 是不是必须把日期转换成毫秒数(长整型)来传输?
- 如果要自定义Jackson的序列化/反序列化器,会不会带来明显的性能损耗?
问题分析与解决方案
为什么解析失败?
Unity的JsonUtility对日期格式的支持非常有限,它只兼容特定格式的ISO 8601字符串,比如yyyy-MM-ddTHH:mm:ss或者带标准时区标识的yyyy-MM-ddTHH:mm:ss.SSSZ。而Jackson默认输出的2018-05-18T22:35:47.760+0000格式(时区用+0000而不是Z),JsonUtility完全无法识别,所以直接返回了DateTime的默认值。
可选的兼容方案
你有两个靠谱的选择,不需要纠结必须用毫秒数:
方案一:转成毫秒级时间戳传输(最稳妥)
这种方式彻底规避了格式兼容问题,前后端处理都简单直接。
后端配置(Jackson注解实现)
给Date字段添加@JsonFormat注解,指定序列化为数字类型的时间戳:
import lombok.Data; import com.fasterxml.jackson.annotation.JsonFormat; import java.util.Date; @Data public class Backend { // 序列化为毫秒级时间戳 @JsonFormat(shape = JsonFormat.Shape.NUMBER) private Date aDate; public Backend() { this.aDate = new Date(); } }
修改后,后端返回的JSON会变成:
{"aDate": 1526663747760}
前端Unity解析逻辑
把C#类中的DateTime字段改成long,然后手动转换为DateTime:
using System; [Serializable] public class FrontEnd { public long aDate; // 新增转换方法,把时间戳转成UTC时间 public DateTime GetUtcDateTime() { return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) .AddMilliseconds(aDate); } // 如果需要本地时间,可以再封装一个方法 public DateTime GetLocalDateTime() { return GetUtcDateTime().ToLocalTime(); } } // 解析代码示例 private IEnumerator AcceptWww(WWW www) { yield return www; var dateObject = JsonUtility.FromJson<FrontEnd>(www.text); DateTime actualDate = dateObject.GetUtcDateTime(); // 现在actualDate就是正确的日期了 }
方案二:修改Jackson输出格式适配Unity
如果不想改变数据类型,可以让Jackson输出JsonUtility能识别的标准ISO 8601格式:
import lombok.Data; import com.fasterxml.jackson.annotation.JsonFormat; import java.util.Date; @Data public class Backend { // 输出Unity兼容的ISO 8601格式,时区设为UTC @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "UTC") private Date aDate; public Backend() { this.aDate = new Date(); } }
修改后,后端返回的JSON会是:
{"aDate": "2018-05-18T22:35:47.760Z"}
此时前端不需要修改FrontEnd类,JsonUtility就能直接正确解析这个日期字符串。
关于自定义序列化的性能损耗
完全不用焦虑!Jackson的注解式序列化(比如@JsonFormat)是框架原生支持的特性,性能和默认序列化几乎没有差距,损耗可以忽略不计。
就算是自己编写自定义的JsonSerializer类,只要逻辑不复杂(比如只是简单的格式转换),性能也不会有明显下降——Jackson的扩展机制设计得非常高效,不会成为接口的性能瓶颈。
内容的提问来源于stack exchange,提问作者Codehai

