2011-02-10 5 views
1

j'essaie de connecter une application à un service externe qui me fournit soit un tableau commeObtenir soit unTableau liste ou une classe

[{"descr":"my description","id":"123"},...] 

ou en cas de quelque chose comme d'erreur

{"error":{"code":123,"message":"my message"}} 

Est existe-t-il un moyen de définir cela comme une classe unique ou de reconnaître le flux par lequel l'objet est-il? Mise à jour 1: J'ai testé plusieurs versions en les exécutant 100 fois dans une boucle et en calculant le temps moyen d'exécution. Dans toutes les différentes versions, j'ai utilisé jackson.


Celui-ci est la référence pour la performance. Il ne remplit pas les exigences de l'entreprise car le code ne fait pas de distinction entre les tableaux et les obejcts.

fcPhotos = mJsonToObjectMapper.readValue(mFcHttpHelper.doGet(urlString), FcPhotos.class); 

Photos: 100 exécutions avec une moyenne durée de: 923ms


L'utilisation d'un analyseur réduit les performances d'environ min. 50%

JsonParser jsonParser = mJsonFactory.createJsonParser(mFcHttpHelper.doGet(urlString)); 

if (jsonParser.nextToken() == JsonToken.START_ARRAY) { 
    fcPhotos = mJsonToObjectMapper.readValue(jsonParser, FcPhotos.class); 
} 

Photos: 100 exécutions avec une moyenne durée: 1585ms


Conversion du InputStream en une chaîne et en maintenant la solution objectMapper.readValue conduit à:

jsonString = inputStreamToString(urlString); 
fcPhotos = mJsonToObjectMapper.readValue(jsonString, FcPhotos.class); 

private final String inputStreamToString(final String urlString) throws UnsupportedEncodingException, IOException { 
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(mFcHttpHelper.doGet(urlString), "UTF8"), 8192); 
    StringBuilder stringBuilder = new StringBuilder(); 
    String line = null; 

    while ((line = bufferedReader.readLine()) != null) { 
     stringBuilder.append(line + "\n"); 
    } 

    bufferedReader.close(); 
    return stringBuilder.toString(); 
} 

Photos: 100 exécutions avec une moyenne. durée: 1191ms


fin de la mise à jour 1


Répondre

1

Une possibilité serait d'utiliser JsonParser pour voir ce qui est le premier jeton (JsonToken.START_ARRAY ou JsonToken.START_OBJECT), puis la liaison de données ne . ObjectMapper peut prendre JsonParser qui pointe vers le premier événement ou n'a pas encore été déplacé vers le premier événement. La combinaison de JsonParser/ObjectMapper est également utile lors du traitement d'un flux de valeurs JSON au niveau racine (comme ce serait le cas pour les flux de style map/reduce ou les entrées de journal lors de l'utilisation de JSON).

Un autre moyen serait d'abord se lier à un modèle d'arbre (JsonNode; ObjectMapper.readTree()); voyez si node est un ObjectNode ou un ArrayNode, puis utilisez ObjectMapper.convertValue (rootNode, desiredClass). Cela a l'avantage que vous pouvez également vérifier les propriétés de l'arbre, dans le cas où il n'y a pas de distinction entre tableau et objet.

+0

Thx StaxMan. Fonctionne comme un charme. Code ressemble maintenant: \t \t \t JsonFactory f = new JsonFactory(); \t \t \t JsonParser jp = f.createJsonParser (photosInput); \t \t \t \t \t \t \t finale JsonToken nextToken = jp.nextToken(); \t \t \t si (nextToken == JsonToken.START_ARRAY) { \t \t \t \t anArray = mJsonToObjectMapper.readValue (jp, AnArray.class); éléments "); \t \t \t} else if (nextToken == JsonToken.START_OBJECT) { \t \t \t \t anError = mJsonToObjectMapper.readValue (jp, AnError.class); \t \t \t \t Log.w (TAG, "Got erreur" + error.code + ":" + error.message); \t \t \t} else { \t \t \t \t Log.w (TAG, "résultat Unknow"); \t \t \t} – lichtzeichenanlage

+0

Génial, heureux que cela fonctionne. – StaxMan

+0

Okay - retour à la case départ. Cela fonctionne - mais est vraiment lent. Environ 70-90% !!! D'autres idées? – lichtzeichenanlage

Questions connexes