2015-11-17 10 views
13

Próbuję parsować następujący ciąg dynamiczny Json String.Parsowanie klucza dynamicznego Json String za pomocą Retrofit

"report":{ 
    "data":{ 
     "results":{ 
      "558952cca6d73d7d81c2eb9d":{ 
       "Max":-1, 
       "Min":-1, 
       "Slope":-1, 
      }, 

      "558ce148a6d73d7d81c2fa8a":{ 
       "Max":-2, 
       "Min":-1, 
       "Slope":-2, 
      } 
     } 
    } 
} 

Po tym, próbuję uzyskać dane, ale otrzymuję błąd podczas analizowania ostatniego dynamicznego ciągu json.

public class Report { 
     @SerializedName("data") 
     @Expose 
     private Data data; 

     public Data getData() { 
      return data; 
     } 

     public void setData(Data data) { 
      this.data = data; 
     } 

     @Override 
     public String toString() { 
      return "Report{" + 
        "data=" + data + 
        '}'; 
     } 
    } 

    public class Data { 
     @SerializedName("results") 
     @Expose 
     private ResultInside result; 

     public ResultInside getResult() { 
      return result; 
     } 

     public void setResult(ResultInside result) { 
      this.result = result; 
     } 
    } 

    public class ResultInside { 
     /*@SerializedName("results") 
     @Expose*/ 
     private Map<String, Vitals> elemDetails = new HashMap<>(); 

     public Map<String, Vitals> getElemDetails() { 
      return elemDetails; 
     } 

     public void setElemDetails(Map<String, Vitals> elemDetails) { 
      this.elemDetails = elemDetails; 
     } 
    } 

Wszelkie sugestie, jak przeanalizować w tym przypadku!

+0

Witam! Znalazłeś rozwiązanie? Miałem ten sam problem. – GensaGames

+0

@GenkaKasyan Sprawdź zaakceptowaną odpowiedź poniżej. – CoDe

+0

@Shubh Hai, Mam ten sam problem, nie wiem jak dodać klasę Pojo dla klucza dynamicznego, czy możesz powiedzieć, czego używałeś w klasie Vitals? – MathaN

Odpowiedz

29

Twoja klasa resultInside dodaje dodatkową warstwę obiektu, która nie istnieje w twoim JSON. Spróbuj przenieść mapę do pola klasy results.

public class Data { 
    @SerializedName("results") 
    @Expose 
    private Map<String, Vitals> result; 

    //.... 
} 
+1

Ci geniusz :) Dzięki. – CoDe

+0

W przypadku retrofitu, jeśli chcesz analizować JSON za pomocą dynamicznych kluczy (z dynamicznymi nazwami), musisz użyć HashMap na pewno. Tak więc ta odpowiedź jest właściwa ode mnie +1. Tylko upewnij się, że umieszczasz HashMap na poziomie obiektu, który ma nazwę statyczną (nie jest to nazwa dynamiczna). – Sniper

+0

Dziękuję bardzo. Uratowałeś moje czasy :) –

1

Lepszym sposobem, aby to zrobić, byłoby:

---------------------- 

public class Report { 
     @SerializedName("data") 
     @Expose 
     private Data data; 

---------------------- 

public class Data { 


    public HashMap<String, DataValues> dataValues; 


    public Data() { 
     this.dataVaues = new HashMap<>(); 
    } 
} 

----------------------------- 

następnie utworzyć klasę Parser takiego:

public class DataParser implements JsonDeserializer<Data> { 


    @Override 
    public Data deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 

     Data result = new Data(); 


     try { 
      final HashMap<String, DataValues> map = readServiceUrlMap(json.getAsJsonObject()); 

      if(map != null) { 
       result.dataValues = map; 
      } 

     }catch (JsonSyntaxException ex){ 
      return null; 
     } 

     return result; 
    } 


    private HashMap<String, DataValues> readServiceUrlMap(final JsonObject jsonObject) throws JsonSyntaxException { 

     if(jsonObject == null) { 
      return null; 
     } 
     Gson gson = new Gson(); 

     HashMap<String, DataValues> products = new HashMap<>(); 

     for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { 

      String key = entry.getKey(); 
      DataValues value = gson.fromJson(entry.getValue(), DataValues.class); 
      products.put(key, value); 
     } 
     return products; 
    } 


---------------------------------------------- 

Następnie wpisz to w swojej klasie ApiClient

public class ApiClient { 


    private static Retrofit retrofit = null; 

    public static Retrofit getClient(String baseUrl) { 

     if(retrofit == null) { 

      GsonBuilder gsonBuilder = new GsonBuilder(); 
      gsonBuilder.registerTypeAdapter(Data.class, new DataParser()); 

      retrofit = new Retrofit.Builder() 
        .baseUrl(baseUrl) 
        .addConverterFactory(GsonConverterFactory.create(gsonBuilder.create())) 
        .build(); 

Mam nadzieję, że to pomoże jeden