Daniel Hernández
Daniel Hernández

Reputation: 310

Class with two fields with same SerializedName

I have a problem with my services because the same field is different form in request and response, whereby I use @Expose annotation to serialize one and deserialize another:

@SerializedName("photo")
@Expose(deserialize = false)
private String imageB64;

@SerializedName("photo")
@Expose(serialize = false)
private ImageURL imageURL;

But in the response, my service is launching an exception:

Caused by: java.lang.IllegalArgumentException: class User declares multiple JSON fields named photo

I'm using Retrofit with GSON converter.

Thanks for your help!

Upvotes: 2

Views: 2958

Answers (2)

Rahul
Rahul

Reputation: 1

@SerializedName("photo")
private Object imageUrl;


public String getImageB64()
{
    return (String) this.imageUrl
}

public void setImageB64( String image )
{
    this.imageUrl = image
}

public ImageURL getimageURL()
{
    return (ImageURL) this.imageUrl
}

public void setimageURL( ImageURL imageUrl )
{
    this.imageUrl = imageUrl
}

Upvotes: 0

user2340612
user2340612

Reputation: 10713

I don't think it's possible to add multiple @SerializedName annotations, because otherwise you'll get the error you provided.

However, you can create a custom TypeAdapter to manually hand serialization/deserialization of your object, like that:

MyObject

public class MyObject {

  private String url;

  private int number;

  // constructor + getters + setters + custom "toString()"
  ...

}

MyObjectTypeAdapter

class MyObjectTypeAdapter extends TypeAdapter<MyObject> {

  @Override
  public void write(JsonWriter out, MyObject value) throws IOException {
    out.beginObject().name("photo").value(value.getUrl()).endObject();
  }

  @Override
  public MyObject read(JsonReader in) throws IOException {
    MyObject result = new MyObject();
    in.beginObject();
    while (in.hasNext()) {
      switch (in.nextName()) {
      case "photo":
        result.setNumber(in.nextInt());
      }
      // other fields
      ...
    }

    in.endObject();
    return result;
  }
}

You can use it in this way:

public static void main(String[] args) {
  Gson gson = new GsonBuilder().registerTypeAdapter(MyObject.class, new MyObjectTypeAdapter()).create();

  System.out.println(gson.toJson(new MyObject("myUrl", 1)));

  MyObject deserialized = gson.fromJson("{ \"photo\": 12 }", MyObject.class);

  System.out.println(deserialized);
}

and it prints (note I used a custom toString() for MyObject):

{"photo":"myUrl"}
MyObject{url='null', number=12}

Upvotes: 1

Related Questions