web-dev-qa-db-fra.com

Comment utiliser l'API Gson de Google pour désérialiser correctement JSON?

En bref, voici une esquisse de l'objet JSON que je veux analyser en Java:

{
    object1: {
            item1: //[String | Array | Object] ,
            item2: // ...
            //<> more items
    object2: { /* .. */ }
    //<> more objects
}

Ce sont les POJO s que j'ai créés pour l'analyse (je laisserai de côté les instructions import par souci de concision):

(1) La représentation de l'objet JSON complet

public class JObjectContainer {

    private List<JObject> jObjects ;

    public JObjectContainer() { }

    //get & set methods

}

(2) La représentation des objets imbriqués:

 public class JObject {

    private String id ;
    private List<JNode> jObjects ;

    public JObject() { } 

    //get & set methods

}

(3) La représentation des articles:

 public class JNode {

    private JsonElement item1 ;
    private JsonElement item2 ;
    //<> more item fields

    public JNode() { }

    //get & set methods

}

Maintenant, en créant une instance Gson (FileReader pour importer le jsonFile),

 Gson gson = new Gson() ;
 JObjectContainer joc = gson.fromJson(jsonFile,JObjectContainer.class) ;

J'obtiens un NullPointerException chaque fois que j'essaie d'accéder à l'objet analysable (par exemple via un ListIterator). Gson fait cependant crée un objet de la classe que j'ai spécifiée et ne fait pas jette toutes les erreurs suivantes.

Je sais que cela a déjà été fait. Alors, qu'est-ce que je manque?

TIA

23
FK82

Ce n'est pas possible. Vous devez modifier votre structure JSON pour représenter object1, object2, etc. comme éléments d'un tablea. Pour l'instant, ce sont les propriétés d'un objet dont on ignore apparemment le nombre (sinon vous n'avez pas tenté de le mapper en tant que List). Gson est intelligent, mais pas qui intelligent :)

Donc, comme exemple de base, cette structure JSON avec un tableau:

{ nodes:
  [
    { item1: 'value1a', item2: 'value2a' },
    { item1: 'value1b', item2: 'value2b' },
    { item1: 'value1c', item2: 'value2c' }
  ]
}

en combinaison avec la Java (qui ne doit pas nécessairement être appelée POJO, mais simplement javabean ou objet de modèle ou objet de valeur).

public class Container {
    private List<Node> nodes;
    // +getter.
}

public class Node {
    private String item1;
    private String item2;
    // +getters.
}

et cet appel Gson

Container container = new Gson().fromJson(json, Container.class);

devrait marcher.

pdate: pour être clair, votre structure JSON est le problème, pas votre Java structure d'objet. En supposant que votre Java structure d'objet) est exactement ce que vous aimeriez finir, alors votre structure JSON devrait ressembler à ceci pour que Gson fasse son travail:

{ jObjects:
  [
    { id: 123, jObjects: 
      [
        { item1: 'value1a', item2: 'value2a' },
        { item1: 'value1b', item2: 'value2b' },
        { item1: 'value1c', item2: 'value2c' }
        /* etc... commaseparated */
      ]
    },
    { id: 456, jObjects: 
      [
        { item1: 'value1d', item2: 'value2d' },
        { item1: 'value1e', item2: 'value2e' },
        { item1: 'value1f', item2: 'value2f' }
        /* etc... commaseparated */
      ]
    }
    /* etc... commaseparated */
  ]
}

Seule la propriété JsonElement doit être remplacée par String, car elle n'est pas valide.

38
BalusC

Je pense que BalusC a donné de bons conseils pour la question spécifique par rapport à GSon (et en général, la liaison de données un à un); mais juste au cas où vous pensez qu'il devrait y avoir une gestion plus dynamique, vous pouvez également envisager d'autres packages de traitement JSON. De nombreux packages ont des façons supplémentaires ou alternatives de mapper les choses: Json-lib, flexjson et Jackson ont au moins des ajouts par rapport à Gson. Certains offrent un mappage plus lâche (vous définissez des noms de choses en types), d'autres prennent en charge les types polymporphiques (déclarant un objet mais peuvent en fait mapper vers un sous-type qui a été sérialisé).

0
StaxMan