简体   繁体   中英

Why is JsonAdapter annotation ignored when serializing built-in type?

The Problem

Imagine the following field:

@JsonAdapter(CustomTypeAdapter.class)
private int field;

When deserializing , the CustomTypeAdapter 's read method is called as usual, but when serializing , the write method is completely ignored and the built-in type is written out as it would ordinarily be. (The same thing happens if I use Integer instead of int .)

The Question

I cannot find anything in the documentation which says that this is the expected behavior. Is it? Or is this a bug?

A Workaround

The only workaround I've been able to find is to create a custom "holder" type and then expose that, eg,

@JsonAdapter(CustomTypeAdapter.class)
class CustomType { /* blah blah */ }

private CustomType field;

public int getField() {
    return field.getValue();
}

public void setField(int field) {
    this.field = new CustomType(field);
}

This works but is a bit more cumbersome.

While I agree that it should not work for int , I can't reproduce the behavior that it doesn't for Integer in Gson 2.3.1. First of all, you must use TypeAdapter<Integer> (or a TypeAdapterFactory ) and not JsonSerializer . It specifically says so in the JsonAdapter Javadoc.

The class referenced by this annotation must be either a TypeAdapter or a TypeAdapterFactory . Using the factory interface makes it possible to delegate to the enclosing Gson instance.

Then, the type is not autoboxed, so if you want to use the annotation, the field must be an Integer . Combining these two facts in a toy example (again, int won't work), we have:

import java.io.IOException;

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

public class JsonAdapterExample {
  public static void main(String[] args) {
    Gson g = new Gson();

    System.out.println(g.toJson(new Car()));
  }

  public static class Car {
    @JsonAdapter(IdAdapter.class)
    Integer id = 10;
  }

  public static class IdAdapter extends TypeAdapter<Integer> {
    @Override
    public Integer read(JsonReader arg0) throws IOException {
      // TODO Auto-generated method stub
      return null;
    }

    @Override
    public void write(JsonWriter arg0, Integer arg1) throws IOException {
      arg0.beginObject();
      arg0.name("id");
      arg0.value(String.valueOf(arg1));
      arg0.endObject();
    } 
  }
}

Output:

{"id":{"id":"10"}}

If it didn't work, it would be 10 not "10" , and there'd be no inner object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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