Java Gson:无法在Android中正确反序列化Joda Time LocalDateTime值

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

我有一个运行在Java web服务器(Jersey Jax RS RI 2.13)上的HTTP REST API,它为我的
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"
    }
]