简体   繁体   English

Gson自定义类型适配器仅在一个对象类型上序列化null?

[英]Gson custom type adapter to serialize null on one object type only?

I'd like to serialize null for only one type in my JSON body that is going on a PUT. 我想在我的JSON主体中仅对一个PUT上的一个类型序列化null。 I don't want to serialize nulls for any other types in the object. 我不想为对象中的任何其他类型序列化null。 I have something like this: 我有这样的事情:

public class Patient {
    public Address address;
    public String first_name;
    public String last_name;
}

and I only want to serialize address if address is null. 如果地址为空,我只想序列化地址。 So for example 所以举个例子

Patient patient = new Patient();
patient.address = null;
patient.last_name = "Doe";

will look something like this: 看起来像这样:

"address":null,
"last_name":"Doe"

Where address is assigned null, patient is left off of the object because by default Gson does not serialize nulls which is what I want, and last name retains the assigned string value. 如果将地址指定为null,则患者不会离开对象,因为默认情况下Gson不会序列化我想要的空值,并且姓氏保留指定的字符串值。

Is there a Gson custom type adapter that I could use? 我可以使用Gson自定义类型适配器吗?

public class GsonCustomAdapter extends TypeAdapter<Address>

I'm not familiar at all with this concept and have been trying to understand it for awhile. 我对这个概念并不熟悉,并且一直试图理解它。 Any help is much appreciated. 任何帮助深表感谢。

If, by default, you don't want to serialize nulls, you can tell the JsonWriter to serialize it only if you are actually reading an Address instance. 如果,默认情况下,您不希望序列化空值,则只有在实际读取Address实例时才能告诉JsonWriter序列化它。

Let's assume the following class: 我们假设以下课程:

class Address {
    public String country = "UK";
    public String city = "London";
}

Now we create a specific type adapter for the Address class. 现在我们为Address类创建一个特定的类型适配器。 This is here where you explicitly say that even if the JsonWriter is not supposed to write null values in the response, you allow it to do so just for the Address field (see the comments in the code). 在这里你明确地说,即使JsonWriter不应该在响应中写入null值,你也允许它只为Address字段这样做(参见代码中的注释)。

class AddressAdapter extends TypeAdapter<Address> {
    @Override
    public void write(JsonWriter out, Address address) throws IOException {
        if (address == null) {
            //if the writer was not allowed to write null values
            //do it only for this field
            if (!out.getSerializeNulls()) {
                out.setSerializeNulls(true);
                out.nullValue();
                out.setSerializeNulls(false);
            } else {
                out.nullValue();
            }
        } else {
            out.beginObject();
            out.name("country");
            out.value(address.country);
            out.name("city");
            out.value(address.city);
            out.endObject();
        }
    }

    @Override
    public Address read(JsonReader in) throws IOException {
        if(in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        in.beginObject();
        Address address = new Address();
        in.nextName();
        address.country = in.nextString();
        in.nextName();
        address.city = in.nextString();
        in.endObject();
        return address;
    }
}

Now you have to register this adapter so that the parser knows he has to use it when serializing/deserializing an Address field. 现在,您必须注册此适配器,以便解析器知道在序列化/反序列化Address字段时必须使用它。 To do that, use the annotation @JsonAdapter . 为此,请使用注释@JsonAdapter

class Patient {
    @JsonAdapter(AddressAdapter.class)
    public Address address;
    public String first_name;
    public String last_name;
}

And it's done! 它已经完成了!

For instance let's take the patient in your example: 例如,让我们以你的例子为例:

Patient patient = new Patient();
patient.last_name = "Doe";

With the parser set to serialize null values, you get: 将解析器设置为序列化空值后,您将获得:

{"address":null,"first_name":null,"last_name":"Doe"}

When you don't allow it (set by default): 当您不允许它时(默认设置):

{"address":null,"last_name":"Doe"}

by setting an address for the patient: 通过为患者设置地址:

patient.address = new Address();
...
{"address":{"country":"UK","city":"London"},"last_name":"Doe"}

As a note if you want to stick with naming conventions on the Java side, you can use the annotation @SerializedName , for instance: 作为一个注释,如果你想在Java端坚持命名约定,你可以使用注释@SerializedName ,例如:

@SerializedName("first_name") public String firstName;
@SerializedName("last_name")  public String lastName;

Hope it helps ! 希望能帮助到你 ! :-) :-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM