The fact is that the bundle does not pass Object through serialization. So I decided to pass a String which you hold to json, and then return it back to Model.

But the fact is that I have 1 window that can work with 3 models, since their adapters are the same. And in order not to create 3 different adapters, I decided to do everything in 1 activation and with 1 adapter.

I have 3 ModelA, ModelB, ModelC. How to find out which model this json belongs to?

Library I use Gson

compile 'com.squareup.retrofit2:converter-gson:2.3.0'

  • one
    Why can't you do it? Show how you tried and what came of it. - Yuriy SPb ♦

2 answers 2

An interesting task ...

The first thing that comes to mind is to transfer 2 objects to the Bundle , one shows the type of json, and the second is json itself:

 //ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ° ModelA modelA; bundle.putInt("type", 1); //ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅ΠΌ Ρ‚ΠΈΠΏ bundle.putString("json", gson.toJson(modelA, ModelA.class); //ΠΏΠΈΡ…Π°Π΅ΠΌ строку json //ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΈΠΊ int type=bundle.getInt("type") String jsonString=bundle.getString("json"); Model model; switch(type) { case 1: model=gson.parseJson(jsonString, ModelA.class); break; case 2: model=gson.parseJson(jsonString, ModelB.class); break; case 3: model=gson.parseJson(jsonString, ModelC.class); break; default: throw new IllegaArgumentException("blah-blah); } 

Update

I remembered how I solved a similar task in my project. Create a custom Gson / json serializer, the task of which is to insert the object type during serialization and its use when deserializing:

 public class ModelSerializer<T extends Model> implements JsonSerializer<T>, JsonDeserializer<T> { private static final String CLASS_META_KEY = "clz"; private final Gson defaultGson; public ModelSerializer() { defaultGson=new Gson(); //Π½ΡƒΠΆΠ΅Π½ Π³ΠΎΠ»Ρ‹ΠΉ экзСмпляр Gson } @Override public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) { JsonElement element=null; if (src == null) { return element; } if (src instanceof ModelA) element = context.serialize(src, ModelA.class); else if (src instanceof ModelB) element = context.serialize(src, ModelB.class); else if (src instanceof ModelC) element = context.serialize(src, ModelC.class); //добавляСм Π² Json свойство - ΠΏΠΎΠ»Π½ΠΎΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ класса element.getAsJsonObject().addProperty(CLASS_META_KEY, src.getClass().getCanonicalName()); return element; } @Override public T deserialize(JsonElement jsonElement, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { Class<?> clz; T model; JsonObject object = jsonElement.getAsJsonObject(); if(object.has(CLASS_META_KEY)) { //опрСдСляСм Ρ‚ΠΈΠΏ String className = object.get(CLASS_META_KEY_RECORD).getAsString(); try { clz = Class.forName(className); } catch (Exception e) { //blah-blah } model = context.deserialize(jsonElement, clz); } else { model=defaultGson.fromJson(jsonElement, typeOfT); } return model; } } 

Now we stick this handler in Gson:

  gson = new GsonBuilder() .registerTypeAdapter(Model.class, new ModelSerializer<Model>()) .serializeNulls() //.setPrettyPrinting() //for debugging .disableHtmlEscaping() .create(); 

further we use this copy of Gson for serialization and deserialization.

With this approach, the entire circus with horses with a type assignment in a separate int type and so on. not needed.

    Another option. We take RuntimeTypeAdapterFactory . Do not be shy, the factory is in the repository of the gson'a, just not included in the library.

     Gson gson = new GsonBuilder() .registerTypeAdapterFactory( RuntimeTypeAdapterFactory .of(Model.class) .registerSubtype(ModelA.class) .registerSubtype(ModelB.class) .registerSubtype(ModelC.class)).create(); Model model = new ModelA(); //Π‘Π΅Ρ€ΠΈΠ°Π»ΠΈΠ·ΡƒΠ΅ΠΌ String json = gson.toJson(model); //ДСсСриализуСм Model parsed = gson.fromJson(json, Model.class); 

    or even

     List<Model> list = new ArrayList<>(); list.add(new ModelA()); list.add(new ModelB()); list.add(new ModelC()); //Π‘Π΅Ρ€ΠΈΠ°Π»ΠΈΠ·ΡƒΠ΅ΠΌ String json = gson.toJson(list); //ДСсСриализуСм List<Model> parsedList = gson.fromJson(json, new TypeToken<List<Model>>(){}.getType()); 

    Threat There seems to be some kind of bug, but it manifests itself in difficult cases (either there is a type field in the class, or some other exotic, you can google it by mistake, there is a fix).