2014-05-02 3 views
3

Je suis confronté à un problème lié à l'analyse json qui a des tableaux mixtes de classes enfants, et je dois fournir cette liste java au client.Parse json avec des objets enfants mixés via gson et renvoyer sous forme de liste

Exemple JSON:

{ 
    "status": "OK", 
    "results": [ 
    { 
     "type": "one", 
     "Id": "2170676", 
     "count": "456", 
     "title": "title", 
     "description": "description", 
     "oneMemberOne": "11", 
     "oneMemberTwo": "12", 
    } 
    { 
     "type": "two", 
     "Id": "2170677", 
     "count": "123", 
     "title": "title", 
     "description": "description", 
     "twoMemberOne": "21", 
     "twoMemberTwo": "22", 
    } 
    ] 
} 

J'ai créé une classe parent et deux classes d'enfants de cette:

Num: Type, Id, comte, titre, champs de description

On étend Num: oneMemberOne, oneMemberTwo

Deux étend Num: twoMemberOne, twoMemberTwo

Ma question: J'ai une méthode pour demander des résultats. Dites-le List<Num> getResults()

  • Je parser les données correctement comme ceci:

    List<Num> result = new ArrayList<Num>(); 
    JsonParser parser = new JsonParser(); 
    JsonObject jsonObject = parser.parse(lastResponsePayload).getAsJsonObject() 
    JsonArray results = jsonObject.get("results").getAsJsonArray(); 
    for (JsonElement element : results) { 
        JsonObject trs = element.getAsJsonObject(); 
        String type = trs.get("type").getAsString(); 
    
        if (type.equals("one") { 
          One one = new Gson().fromJson(element, One.class); 
          result.add(product); 
        } else if (type.equals("two") { 
          Two two = new Gson().fromJson(element, Two.class); 
          result.add(metaproduct); 
        } 
    return result; 
    
  • Maintenant, côté client, après que je reçois la liste, je dois le faire:

    List<Num> results = getResults(); 
    List<One> oness = new ArrayList<One>(); 
    List<Two> twoss = new ArrayList<Two>(); 
    for(Num n : results) { 
        if(n.type.equals("one") 
          oness.add((One) n); 
        else 
          twoss.add((Two) n); 
    

Est-ce une bonne conception pour ce scénario?

L'utilisateur de cette API doit redescendre à chaque fois en fonction du champ type de la classe parente. Parce que webservice me donne un mélange de classes d'enfants, je dois le faire. Y a-t-il une meilleure approche à ce problème?

  • Une autre approche dans mon esprit est de créer une classe Result qui contient deux membres One et Two et de fournir mon un List<Result> au lieu de List<Num>, mais l'utilisateur doit vérifier si membre est null ou non et prendre les mesures appropriées.

Merci d'avance.

Répondre

3

Je vais suggérer que vous avez une autre classe quelque chose comme ça. Cela empêche le code client de tourner à nouveau dans la liste et d'analyser les enregistrements. Veuillez noter que je n'ai pas exécuté ce code pour le tester.

public class Result { 
    private List<One> oness; 
    private List<Two> twoss; 

    public List<One> getOness() { 
     return oness; 
    } 

    public void setOness(List<One> oness) { 
     this.oness = oness; 
    } 

    public List<Two> getTwoss() { 
     return twoss; 
    } 

    public void setTwoss(List<Two> twoss) { 
     this.twoss = twoss; 
    } 
} 

Et changer

List<Num> getResults()

Pour

Result getResults()

également à l'utilisateur ne devra pas vérifier si vous modifiez nulls votre logique d'analyse syntaxique. S'il vous plaît voir que dans le cas où nous n'avons pas de résultats, nous ne retournons pas la liste nulle, mais EmptyList.

Result result = new Result(); 
    JsonParser parser = new JsonParser(); 
    JsonObject jsonObject = parser.parse(lastResponsePayload).getAsJsonObject() 
    JsonArray results = jsonObject.get("results").getAsJsonArray(); 

    List<One> oness = null; 
    List<Two> twoss = null; 

    for (JsonElement element : results) { 
     JsonObject trs = element.getAsJsonObject(); 
     String type = trs.get("type").getAsString(); 

     if (type.equals("one")) { 
      if(oness == null) { 
       oness = new ArrayList<One>(); 
       result.setOness(oness); 
      } 
      One one = new Gson().fromJson(element, One.class); 
      oness.add(product); 
     } else if (type.equals("two")) { 
      if(twoss == null) { 
       twoss = new ArrayList<Two>(); 
       result.setTwoss(twoss); 
      } 
       Two two = new Gson().fromJson(element, Two.class); 
       twoss.add(metaproduct); 
     } 
     if(oness == null) { 
      result.setOness(Collections.<One>EMPTY_LIST); 
     } 
     if(twoss == null) { 
      result.setTwoss(Collections.<Two>EMPTY_LIST); 
     } 

    return result; 

Hope it helps :)

+0

Merci. Je pense déjà à cette solution. Je ne voulais pas mettre un autre code dans la question. C'est totalement valable et une autre solution à la question. Nous avons décidé de réparer le service Web car il ne devrait pas donner de résultats de classes mélangées dans un seul compartiment. Et puis utiliser une classe similaire à la vôtre sera parfaitement ok et gson l'analysera automatiquement et facilement. Je vais fermer la question car il n'y a pas qu'une seule réponse. –

+0

Si vous êtes d'accord, c'est une réponse possible. L'accepteras-tu comme une réponse? – vkg

+1

@Jabbar_Jigariyo: au lieu de renvoyer une instance de la classe dédiée qui sépare les objets, vous devriez retourner un 'List ' comme vous l'avez fait en premier. Parce que certains clients peuvent être intéressés par toute la liste, pas une liste divisée en deux, en particulier si l'ordre des éléments est important: ils perdent une information et ont plus de traitement à faire de leur côté. Au lieu de cela, fournissez une classe avec une méthode statique qui divise la 'List ' et renvoie l'équivalent de la classe 'Result' décrite ici. De cette façon, les clients ont le choix. – Pragmateek