Search code examples
javajsongsonpojojson-deserialization

Two differents types of responses in POJO


I'm using Retrofit with POJO, which usually works, but the answer has two different objects depending on whether the result is valid. Which one is a String and the another is an Object:

{
  "data":"No results."  
}

or:

{
  "data": {
    "exame": [
      {
        "id": 776,
        "codigo": "DHT",
        "instrucao": "- Text."
      },
      {
        "id": 776,
        "codigo": "DHT",
        "instrucao": "- Text"
      }
    ]
  }
}

And my class:

public class Exame {

    @SerializedName("data")
    @Expose
    @Nullable
    private ExameItem exameItem;
    private String mensagem;

    public ExameItem getExameItem() {
        return exameItem;
    }

    public void setExameItem(ExameItem exameItem) {
        this.exameItem = exameItem;
    }

    public String getMensagem() {
        return mensagem;
    }

    public void setMensagem(String mensagem) {
        this.mensagem = mensagem;
    }
}

When I do Exame().getExameItem its fine, but when I try test if have a message in Exame().getMessagem its bring me a this error:

java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 10 path $.data

So, I think how can I test if @data is a String of an Object, but I don't kwon how, anyone may help?


Solution

  • You need to implement custom deserialiser by implementing JsonDeserializer interface. See below example:

    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    import com.google.gson.JsonDeserializationContext;
    import com.google.gson.JsonDeserializer;
    import com.google.gson.JsonElement;
    import com.google.gson.JsonObject;
    import com.google.gson.JsonParseException;
    import com.google.gson.annotations.JsonAdapter;
    
    import java.io.File;
    import java.io.FileReader;
    import java.lang.reflect.Type;
    import java.util.List;
    
    public class GsonApp {
    
        public static void main(String[] args) throws Exception {
            File jsonFile = new File("./resource/test.json").getAbsoluteFile();
    
            Gson gson = new GsonBuilder().create();
    
            System.out.println(gson.fromJson(new FileReader(jsonFile), Exame.class));
        }
    }
    
    class ExamsJsonDeserializer implements JsonDeserializer<Exame> {
    
        @Override
        public Exame deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            JsonObject root = json.getAsJsonObject();
            JsonElement data = root.get("data");
    
            Exame exam = new Exame();
            if (data.isJsonPrimitive()) {
                exam.setMensagem(data.getAsString());
            } else {
                ExameItem examItem = context.deserialize(data, ExameItem.class);
                exam.setExameItem(examItem);
            }
            return exam;
        }
    }
    
    @JsonAdapter(ExamsJsonDeserializer.class)
    class Exame {
    
        private ExameItem exameItem;
        private String mensagem;
    
        // getters, setters, toString
    }
    
    class ExameItem {
    
        private List<Item> exame;
    
        //getters, setters, toString
    }
    
    class Item {
    
        private int id;
        // ...
        //getters, setters, toString
    }