2010-11-02 6 views
1

Je suis en train d'analyser une structure JSON similaire à celui-ci:Parsing JSON dans Map <String, entité> avec FlexJSON

{ 
"cars": { 
    "112": { 
    "make": "Cadillac", 
    "model": "Eldorado", 
    "year": "1998" 
    }, 
    "642": { 
    "make": "Cadillac", 
    "model": "Eldorado", 
    "year": "1990" 
    }, 
    "9242": { 
    "make": "Cadillac", 
    "model": "Eldorado", 
    "year": "2001" 
    } 
}} 

J'ai une classe CarEntity définie avec makeName, modèle, les attributs année définis et accessibles via setters/getters.

Je suis en train de désérialiser cette JSON comme ceci:

Map<String, CarEntity> deserialized = new JSONDeserializer<Map<String, CarEntity>>() 
    .use("cars.values", Map.class) 
    .deserialize(json); 

et il ne fonctionne pas :(Il ne désérialiser mais pas en Map<String, CarEntity> mais plutôt en carte profonde (quelque chose comme Map<String, Map<String, Map<String, String>>>)

Qu'est-ce que je fais mal

Répondre

2

Votre problème est que votre json a deux cartes. Un qui contient la clé «voitures», et celui qui contient la CarEntity réelle. Malheureusement, vous ne pouvez pas faire référence à une seule touche dans une carte et attribuer des types sur cette seule clé pour le moment. En règle générale, définir les types sur les valeurs pour les collections fait référence à toutes les valeurs de la collection. Vous n'avez pas besoin de spécifier les types pour la première carte contenant la clé "cars" car elle la désérialisera par défaut.

Map<String, CarEntity> deserialized = new JSONDeserializer<Map<String,Map<String, CarEntity>>>() 
    .use("values.values", CarEntity.class) 
    .deserialize(json).get("cars"); 

Le chemin « values.values ​​» fait référence aux valeurs de Carte extérieure parcouraient alors les valeurs suivantes de carte sont toutes les instances de CarEntity. J'ai envisagé de modifier les expressions de chemin pour qu'elles soient plus expressives, ce qui vous permet de cibler une seule valeur dans une collection, mais cela augmente les frais généraux liés à leur évaluation et la rétrocompatibilité est un défi.

0

ajouter Encore un appel à get("cars") comme:

Map<String, CarEntity> deserialized = new JSONDeserializer<Map<String, CarEntity>>() 
    .use("cars.values", Map.class) 
    .deserialize(json).get("cars"); 

chaîne JSON a probablement été publié en feuilleton à partir d'une cars variable de type Map<String, CarEntity>

+0

Cela n'a vraiment pas aidé. Renvoie évidemment une carte différente, mais c'est toujours une carte de chaînes, plutôt que des objets d'entité –

1

Vous êtes le plus susceptible d'être mordu par Java Type Erasure: bibliothèque JSON en question ne sait pas le type que vous voulez; tout ce qu'il voit est l'équivalent de la carte. Vous devez donc spécifier au moins le type de valeur en quelque sorte. Espérons que la documentation de FlexJSON indique comment.

Vous pouvez également classer HashMap dans votre propre type (MyEntityMap étend HashMap), car les informations de type peuvent être déduites du super type générique; et en passant MyEntityMap.class donnerait des informations de type que la plupart des bibliothèques JSON peuvent utiliser (Jackson et GSON au moins).

Si cela ne fonctionne pas, les bibliothèques Jackson et GSON peuvent facilement gérer ce cas d'utilisation; les deux ont des méthodes pour spécifier des types génériques pour la désérialisation.

Questions connexes