仅使用JsonDeserilization和@JsonAdapter

时间:2019-01-20 21:35:05

标签: java gson

在通过@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状态:

  

此批注引用的类必须是TypeAdapterTypeAdapterFactory,或者必须实现JsonDeserializerJsonSerializer之一或两者。   (强调)

因此,我从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>的类。由于我只能将MyJobDeserializerGsonBuilder.registerTypeAdapter(...)一起使用,因此该类似乎还可以。

我在做什么错?能够使用注释和标准的Gson序列化会更好。

谢谢!

0 个答案:

没有答案