在通过@JsonAdapter进行注释并且仅实现JsonDeserializer
时,关于序列化,我对Gson和字段注释存在疑问。
作为一个例子,我有一个简单的界面和实现
public interface IMyJob
{
String getJobName();
String getJobId();
}
public class MyJobImpl implements IMyJob
{
final String jobName;
final String jobId;
public MyJobImpl(String jn, String ji)
{
this.jobName = jn;
this.jobId = ji;
}
@Override
public String getJobId()
{
return jobId;
}
@Override
public String getJobName()
{
return jobName;
}
}
然后我希望在另一个类中使用该接口:
public interface IStatus
{
String getStatus();
IMyJob getJob();
}
public class Status implements IStatus
{
private final String status;
private final IMyJob job;
/* package */ Status(String status,
IMyJob job)
{
this.status = status;
this.job = job;
}
@Override
public String getStatus()
{
return status;
}
@Override
public IMyJob getJob()
{
return job;
}
// really from a factory, but example for SO
public static IStatus create(String status, IMyJob job)
{
return new Status(status, job);
}
}
我做一个简单的往返json测试:
IMyJob job = new MyJobImpl("Hello World", "123");
IStatus status = Status.create("Getting Warmer", job);
// To there
String json = new Gson().toJson(status);
// And back
// use builder so can later add the examples
GsonBuilder gb = new GsonBuilder();
IStatus chk = gb.create().fromJson(json, Status.class);
不做任何修改,对json进行/从json收到(按预期)
java.lang.RuntimeException:无法为以下参数调用无参数构造函数 com.example.explore.IMyJob界面。注册InstanceCreator 与Gson一起使用可解决此问题。
at com.google.gson.internal.ConstructorConstructor \ $ 14.construct(ConstructorConstructor.java:228)
在com.google.gson.internal.bind.ReflectiveTypeAdapterFactory \ $ Adapter.read(ReflectiveTypeAdapterFactory.java:212)
在com.google.gson.internal.bind.ReflectiveTypeAdapterFactory \ $ 1.read(ReflectiveTypeAdapterFactory.java:131)
在com.google.gson.internal.bind.ReflectiveTypeAdapterFactory $ Adapter.read(ReflectiveTypeAdapterFactory.java:222)
在com.google.gson.Gson.fromJson(Gson.java:927)
在com.google.gson.Gson.fromJson(Gson.java:892)
在com.google.gson.Gson.fromJson(Gson.java:841)
在com.google.gson.Gson.fromJson(Gson.java:813)
...
所以我写了一个简单的反序列化器:
public class MyJobDeserializer
implements JsonDeserializer<IMyJob>
{
@Override
public IMyJob deserialize(JsonElement json,
Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException
{
JsonObject jsonObj = json.getAsJsonObject();
return new MyJobImpl(jsonObj.get("jobName").getAsString(),
jsonObj.get("jobId").getAsString());
}
}
并在.fromJson(...)
调用之前添加到GsonBuilder:
JsonDeserializer<IMyJob> imyjobD = new MyJobDeserializer();
gb.registerTypeAdapter(IMyJob.class, imyjobD);
成功!到目前为止,一切都很好。
gson 2.8.5 javadocs for the @JsonAdapter状态:
此批注引用的类必须是
TypeAdapter
或TypeAdapterFactory
,,或者必须实现JsonDeserializer
或JsonSerializer
之一或两者。 (强调)
因此,我从GsonBuilder中删除了JsonDeserializer
,并在Status类中添加了一个注释,因此:
public class Status implements IStatus
{
private final String status;
@JsonAdapter(MyJobDeserializer.class)
private final IMyJob job;
...
但是,当这种方法运行时,job
对象的值在首次调用时不会写入json字符串。
因此,上述.toJson(...)
的输出给出了此输出(缺少工作信息):
{"status":"Getting Warmer","job":{}}
我可以通过将JsonSerializer<IMyJob>
添加到MyJobDeserializer
类来解决这种情况,或者通过编写实现TypeAdapter<IMyJob>
的新类来解决。
但是javadocs似乎暗示我应该能够传递 just 实现JsonDeserializer<IMyJob>
的类。由于我只能将MyJobDeserializer
与GsonBuilder.registerTypeAdapter(...)
一起使用,因此该类似乎还可以。
我在做什么错?能够使用注释和标准的Gson序列化会更好。
谢谢!