英文:
GSON Has Different Behaviour in Unit Test vs Deployed Code
问题
以下是您要翻译的内容:
我正在尝试将GSON集成到现有项目中,以序列化和反序列化一个由大多数POJO组成的预先存在的复杂数据结构。我编写了一个JUnit测试来验证是否成功,如下所示:
@Test
public void testJsonSerialization() throws Exception {
Gson gson = new GsonBuilder().create();
MyObject myObject = generateMyObject();
//Convert to JSON
String json = gson.toJson(myObject);
//Convert to MyObject
MyObject newMyObject = gson.fromJson(json, MyObject.class);
//Compare
assertEquals(myObject, newMyObject);
}
这个单元测试成功通过,但在我的生产代码中使用时,由于缺少无参构造函数,反序列化失败:
public void onHttpPostRequest(HttpRequest request){
Gson gson = new GsonBuilder().create();
try{
validateHttpPostRequest(request);
MyObject myObject = gson.fromJson(request.getContentAsString(), MyObject.class);
//继续处理请求
} catch(Exception e) {
logger.warn("Failed to parse incoming Request", e);
}
}
导致以下异常:
Failed to parse incoming Request
java.lang.RuntimeException: Unable to invoke no-args constructor for class com.example.MyChildObject. Registering an InstanceCreator with Gson for this type may fix this problem.
at com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:228)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:212)
at com.google.gson.Gson.fromJson(Gson.java:932)
at com.google.gson.Gson.fromJson(Gson.java:1003)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.deserialize(TreeTypeAdapter.java:162)
at com.example.Message$JsonAdapter.deserialize(Message.java:230)
at com.example.Message$JsonAdapter.deserialize(Message.java:188)
at com.google.gson.internal.bind.TreeTypeAdapter.read(TreeTypeAdapter.java:69)
at com.google.gson.TypeAdapter$1.read(TypeAdapter.java:199)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
at com.google.gson.Gson.fromJson(Gson.java:932)
at com.google.gson.Gson.fromJson(Gson.java:897)
at com.google.gson.Gson.fromJson(Gson.java:846)
at com.google.gson.Gson.fromJson(Gson.java:817)
我绝对没有问题来解决这个问题,但是由于单元测试不具有代表性,我们无法百分之百确定在复杂数据类型中是否遗漏了任何类。
是否有任何原因导致GSON在单元测试中的行为与生产代码中的行为不同呢?
英文:
I am trying to integrate GSON into an existing project to serialise and de-serialise a pre-existing complex data structure consisting of mostly POJOs. I have written a JUnit test to verify this is successful as follows:
@Test
public void testJsonSerialization() throws Exception {
Gson gson = new GsonBuilder().create();
MyObject myObject = generateMyObject();
//Convert to JSON
String json = gson.toJson(myObject);
//Convert to MyObject
MyObject newMyObject = gson.fromJson(json, MyObject.class);
//Compare
assertEquals(myObject, newMyObject);
}
This unit test passes successfully, but when used in my production code the de-serialisation fails due to missing no-arg constructors:
public void onHttpPostRequest(HttpRequest request){
Gson gson = new GsonBuilder().create();
try{
validateHttpPostRequest(request);
MyObject myObject = gson.fromJson(request.getContentAsString(), MyObject.class);
//continue processing request
} catch(Exception e) {
logger.warn("Failed to parse incoming Request", e);
}
}
Resulting in the following exception:
Failed to parse incoming Request
java.lang.RuntimeException: Unable to invoke no-args constructor for class com.example.MyChildObject. Registering an InstanceCreator with Gson for this type may fix this problem.
at com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:228)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:212)
at com.google.gson.Gson.fromJson(Gson.java:932)
at com.google.gson.Gson.fromJson(Gson.java:1003)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.deserialize(TreeTypeAdapter.java:162)
at com.example.Message$JsonAdapter.deserialize(Message.java:230)
at com.example.Message$JsonAdapter.deserialize(Message.java:188)
at com.google.gson.internal.bind.TreeTypeAdapter.read(TreeTypeAdapter.java:69)
at com.google.gson.TypeAdapter$1.read(TypeAdapter.java:199)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
at com.google.gson.Gson.fromJson(Gson.java:932)
at com.google.gson.Gson.fromJson(Gson.java:897)
at com.google.gson.Gson.fromJson(Gson.java:846)
at com.google.gson.Gson.fromJson(Gson.java:817)
I have absolutely no problem with fixing the issue but as the unit test is not representative we cannot be 100% certain that we have not missed any classes in our complex datatype.
Is there any reason why GSON behaviour may be different in a unit test compared to production code?
专注分享java语言的经验与见解,让所有开发者获益!
评论