Java Gson:无法在Android中正确反序列化Joda Time LocalDateTime值
我有一个运行在Java web服务器(Jersey Jax RS RI 2.13)上的HTTP REST API,它为我的Java Gson:无法在Android中正确反序列化Joda Time LocalDateTime值,java,android,jackson,gson,jodatime,Java,Android,Jackson,Gson,Jodatime,我有一个运行在Java web服务器(Jersey Jax RS RI 2.13)上的HTTP REST API,它为我的AssetBooking对象提供了一个用Jackson序列化的ArrayList。在Android端,我有相同的对象,我用Gson反序列化它 所有其他对象的反序列化都很好,AssetBooking对象的其他字段的反序列化也很好 这是我的反序列化方法: public ArrayList<AssetBooking> getAssetBookings (String j
AssetBooking
对象提供了一个用Jackson序列化的ArrayList
。在Android端,我有相同的对象,我用Gson反序列化它
所有其他对象的反序列化都很好,AssetBooking
对象的其他字段的反序列化也很好
这是我的反序列化方法:
public ArrayList<AssetBooking> getAssetBookings (String json) {
Gson gson = new Gson();
ArrayList<AssetBooking> assetBookings = gson.fromJson(json, new TypeToken<ArrayList<AssetBooking>>(){}.getType());
return assetBookings;
}
Android端接收到的JSON字符串(它只有一个对象,但我必须剪切日期变量createdOn
和updatedOn
,这样就不会破坏StackOverflow的最大post大小):
作为一个实验,我在反序列化后序列化了对象(而不是数组),结果如下:
{
"assetId": 1,
"createdOn": {
"iChronology": {
"iBase": {
"iMinDaysInFirstWeek": 4
}
},
"iLocalMillis": 1492419018809
},
"fromDatetime": {
"iChronology": {
"iBase": {
"iMinDaysInFirstWeek": 4
}
},
"iLocalMillis": 1492419014536
},
"id": 0,
"status": true,
"toDatetime": {
"iChronology": {
"iBase": {
"iMinDaysInFirstWeek": 4
}
},
"iLocalMillis": 1492419018793
},
"updatedOn": {
"iChronology": {
"iBase": {
"iMinDaysInFirstWeek": 4
}
},
"iLocalMillis": 1492419018831
},
"userEmail": "fabio@blabla.bla",
"userId": 1,
"userLastName": "Lanza",
"userName": "Fabio"
}
您的JSON非常臃肿,毫无原因。请注意,并非每个类都被设计为(反)序列化,特别是对于像Jackson或Gson这样的非标准库(Joda Time为什么要同时关注Gson和Jackson本身?)。这两个库足够聪明,可以使用Java反射(反)序列化,但它们不知道给定类是否有理由(反)序列化。如果在两侧使用相同库的不同版本,情况可能会更糟,因为无法确保这些对象是二进制兼容的。更重要的是:你不应该对一个特定的对象二进制结构做任何假设,只为了你的利益而使用它的公共API。您所要做的就是让这些库知道这些类,并定义它们的实例(非)序列化的方式 为简单起见,您可以使用字符串对
LocalDateTime
实例进行编码/解码:这是最简单的方法,可与Joda Time完美配合使用:
编码李>LocalDateTime.toString()
进行解码LocalDateTime.parse()
newlocaldatetime(2017,4,16,17,15)
可以作为2017-04-16T17:15:00.000
进行“字符串化”。这足以恢复原始日期。当然,如果需要,可以使用自定义格式化程序
“服务器”
最终类服务器{
专用服务器(){
}
静态InputStream produceResponse()
抛出IOException{
final ByteArrayOutputStream ByteArrayOutputStream=新建ByteArrayOutputStream();
objectMapper.writeValue(byteArrayOutputStream,有效负载);
返回新的ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
私有静态最终LocalDateTime日期=新的LocalDateTime(2017,4,16,17,15);
私有静态最终列表有效负载=ImmutableList.of(
新资产bookingjacksondto(1,10,100,date,date,true,date,date),foo,bar,foo。bar@email")
);
私有静态最终ObjectMapper ObjectMapper=createObjectMapper();
私有静态对象映射器createObjectMapper(){
最终ObjectMapper ObjectMapper=新ObjectMapper();
//在这里,我们只是定义我们不需要getter,为了简洁起见,我们将使用字段
返回对象映射器
.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(任何)
.WithGettServiceability(无)
.具有可视性(无)
.WithCreator可见性(无)
)
//这里是注册LocalDateTime序列化策略的位置
.registerModule(新的SimpleModule()
.addSerializer(LocalDateTime.class,新的LocalDateTimeJsonSerializer())
);
}
@抑制警告(“未使用”)
私有静态最终类资产bookingjacksondto{
私有最终int id;
私人最终综合资产;
私有最终int用户标识;
私有最终LocalDateTime fromDatetime;
私有最终LocalDateTime到DateTime;
私有最终布尔状态;
私有最终LocalDateTime createdOn;
private final LocalDateTime UpdateOn;
私有最终字符串用户名;
私有最终字符串userLastName;
私人最终字符串用户电子邮件;
私有资产bookingJacksondto(final int id,final int assetId,final int userId,final LocalDateTime from datetime,final LocalDateTime to datetime,
最终布尔状态、最终LocalDateTime createdOn、最终LocalDateTime UpdateOn、最终字符串用户名、最终字符串userLastName、,
最终字符串(用户电子邮件){
this.id=id;
this.assetId=assetId;
this.userId=userId;
this.fromDatetime=fromDatetime;
this.toDatetime=toDatetime;
这个状态=状态;
this.createdOn=createdOn;
this.updatedOn=updatedOn;
this.userName=用户名;
this.userLastName=userLastName;
this.userEmail=userEmail;
}
}
私有静态最终类LocalDateTimeJsonSerializer
扩展JsonSerializer{
@凌驾
public void序列化(最终LocalDateTime LocalDateTime、最终JsonGenerator生成器、最终SerializerProvider序列化器)
抛出IOException{
//只需将其编码为一个简单的字符串--这就是您所需要的
generator.writeString(localDateTime.toString());
}
}
}
“客户”
final类客户端{
私人客户(){
}
静态响应(最终读卡器){
最终列表负载=gson.fromJson(reader,assetBookingListType);
用于(最终资产记账第二至资产记账:有效载荷){
System.out.println(assetBooking.assetId+”:“+assetBooking.createdOn);
}
}
//TypeToken.getType()结果是常量,可以保存以重复使用
私人静态国际泳联
{
"assetId": 1,
"createdOn": {
"iChronology": {
"iBase": {
"iMinDaysInFirstWeek": 4
}
},
"iLocalMillis": 1492419018809
},
"fromDatetime": {
"iChronology": {
"iBase": {
"iMinDaysInFirstWeek": 4
}
},
"iLocalMillis": 1492419014536
},
"id": 0,
"status": true,
"toDatetime": {
"iChronology": {
"iBase": {
"iMinDaysInFirstWeek": 4
}
},
"iLocalMillis": 1492419018793
},
"updatedOn": {
"iChronology": {
"iBase": {
"iMinDaysInFirstWeek": 4
}
},
"iLocalMillis": 1492419018831
},
"userEmail": "fabio@blabla.bla",
"userId": 1,
"userLastName": "Lanza",
"userName": "Fabio"
}
[
{
"id": 1,
"assetId": 10,
"userId": 100,
"fromDatetime": {
"iLocalMillis": 1492362900000,
"iChronology": {
"iBase": {
"iBase": null,
"iParam": null,
"iMinDaysInFirstWeek": 4
},
"iParam": null
}
},
"toDatetime": {
"iLocalMillis": 1492362900000,
"iChronology": {
"iBase": {
"iBase": null,
"iParam": null,
"iMinDaysInFirstWeek": 4
},
"iParam": null
}
},
"status": true,
"createdOn": {
"iLocalMillis": 1492362900000,
"iChronology": {
"iBase": {
"iBase": null,
"iParam": null,
"iMinDaysInFirstWeek": 4
},
"iParam": null
}
},
"updatedOn": {
"iLocalMillis": 1492362900000,
"iChronology": {
"iBase": {
"iBase": null,
"iParam": null,
"iMinDaysInFirstWeek": 4
},
"iParam": null
}
},
"userName": "foo",
"userLastName": "bar",
"userEmail": "foo.bar@email"
}
]
[
{
"id": 1,
"assetId": 10,
"userId": 100,
"fromDatetime": "2017-04-16T17:15:00.000",
"toDatetime": "2017-04-16T17:15:00.000",
"status": true,
"createdOn": "2017-04-16T17:15:00.000",
"updatedOn": "2017-04-16T17:15:00.000",
"userName": "foo",
"userLastName": "bar",
"userEmail": "foo.bar@email"
}
]