2010-09-22 7 views
12

J'utilise gson pour analyser json en java beans. Pour l'API que j'utilise, un grand nombre de résultats json incluent le résultat en tant que première propriété d'un objet json. La "méthode gson" semble être de créer un objet Java wrapper équivalent, qui a une propriété pour le type de sortie cible - mais cela entraîne des classes inutiles. Existe-t-il une meilleure façon de faire?Quelle est la manière la plus simple d'analyser json en utilisant gson lorsque l'élément à analyser est un élément d'une chaîne json?

Par exemple, pour analyser: {"profile":{"username":"nickstreet","first_name":"Nick","last_name":"Street"}}

que je dois faire:

public class ParseProfile extends TestCase { 
    public void testParseProfile() { 
     Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); 
     String profileJson = "{\"profile\":{\"username\":\"nickstreet\",\"first_name\":\"Nick\",\"last_name\":\"Street\"}}"; 
     ProfileContainer profileContainer = gson.fromJson(profileJson, ProfileContainer.class); 
     Profile profile = profileContainer.getProfile(); 
     assertEquals("nickstreet", profile.username); 
     assertEquals("Nick", profile.firstName); 
     assertEquals("Street", profile.lastName); 
    } 
} 

public class ProfileContainer { 
    protected Profile profile; 

    public Profile getProfile() { 
     return profile; 
    } 

    public void setProfile(Profile profile) { 
     this.profile = profile; 
    } 
} 

public class Profile { 
    protected String username; 
    protected String firstName; 
    protected String lastName; 

    public String getUsername() { 
     return username; 
    } 
    public void setUsername(String username) { 
     this.username = username; 
    } 
    public String getFirstName() { 
     return firstName; 
    } 
    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 
    public String getLastName() { 
     return lastName; 
    } 
    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 
} 

Bien sûr, une approche alternative à l'utilisation d'un conteneur serait d'enlever manuellement la partie extérieure de la chaîne (par exemple supprimer le "profil": {et fermeture}) en utilisant des techniques d'analyse de chaîne standard, mais cela semble être la mauvaise approche.

Je voudrais pouvoir faire quelque chose comme:

Profile p = gson.fromJsonProperty(json, Profile.class, "profile"); 

This issue suggère qu'il devrait être possible de briser une chaîne JSON en un objet JSON, pour tirer un jsonElement de cet objet, et passer dans json.fromJson(). Cependant, la méthode toJsonElement() ne fonctionne que sur un objet java, pas sur une chaîne json.

Est-ce que quelqu'un a une meilleure approche?

Répondre

8

J'ai rencontré le même problème. Fondamentalement, ce que vous faites pour éviter tout le non-sens de classe de conteneur est juste utiliser les fonctions JSONObject pour récupérer l'objet interne que vous essayez de désérialiser. Pardonnez-moi pour le code bâclé, mais il va quelque chose comme ceci:

GsonBuilder gsonb = new GsonBuilder() 
Gson gson = gsonb.create(); 

JSONObject j; 
JSONObject jo; 

Profile p = null; 

try { 

    j = new JSONObject(convertStreamToString(responseStream)); 
    jo = j.getJSONObject("profile"); // now jo contains only data within "profile" 
    p = gson.fromJson(jo.toString(), Profile.class); 
    // now p is your deserialized profile object 
}catch(Exception e) { 
    e.printStackTrace(); 
} 
+2

Merci pour la réponse. Ce n'est pas tout à fait correct, mais cela m'a conduit à la bonne réponse. Vous ne pouvez pas créer directement un JsonObject avec une chaîne, vous devez utiliser JsonParser pour le créer. JsonParser parser = new JsonParser(); JsonObject j = (JsonObject) parser.parse (json); –