web-dev-qa-db-fra.com

Comment traiter un gros objet JSON sur Android

Je crée une application Android qui exécute un WebService ASP.NET. Webservice envoie un objet JSON et l'application analyse l'objet et l'affiche à l'écran. Dans un cas, l'objet JSON est trop volumineux et l'erreur échouant dans la transaction de reliure m'arrive. Ma solution est d’obtenir cet objet JSON et de l’incorporer dans le code de l’application, de sorte qu’il n’ait pas besoin de le récupérer du serveur. Pouvez-vous dire d’autres choses que je peux faire pour résoudre ce problème? Ou pouvez-vous me dire comment obtenir cet objet JSON auprès de Webservice? Merci.

13
jason

Envoi des données grande taille du serveur au mobile. JSON est léger .. Si vous souhaitez transmettre les données de manière plus efficace, passez-les en pagination. Si vous souhaitez utiliser protocole plus léger que JSON, implémentez le protocole Google ci-dessous qui sont vraiment utiles et qui prennent en charge les principaux langages . Vous trouverez ci-dessous une structure de données sérialisée plus petite. Protocole d'échange de données de Google.

1.Google Protocol

2.Flat Buffers

3.Nano-proto buffers

J'espère que cela vous sera utile.

12
Maheshwar Ligade

Si les données sont volumineuses, essayez de les enregistrer dans la base de données, puis utilisez SQLite. (mais non recommandé si c'est dynamique) 

Pour analyser un objet json, utilisez gson ou jackson. Cela permettra de réduire considérablement la consommation de mémoire, car les données json sont partiellement analysées . Obtenez Gson, jackson ici https://sites.google.com/site/gson/gson-user-guidehttp://jackson.codehaus.org/

Un exemple jackson http://www.mkyong.com/Java/jackson-streaming-api-to-read-and-write-json/

4
Niroshan

Première chose: s'il y a un crash ou une exception dans votre code, vous voudrez probablement le poster. "Failed Binder Exception" est un peu trop vague pour comprendre ce que vous faites.

Si vous souhaitez vraiment intégrer votre application Android avec JSON incorporé (pour éviter de la récupérer depuis un serveur, envisagez de la stocker en tant qu'actif et accédez-y à l'aide de AssetManager . Vous déposez le fichier avec le json dans le dossier des ressources de votre application et lisez-les avec AssetManager.

Si vous souhaitez toujours le télécharger à partir du serveur et y donner suite, envisagez d'utiliser des API de transmission en continu pour télécharger et analyser le JSON. JSONObject d'Android ne fait pas cela et insiste pour que toute la chaîne JSON soit en mémoire avant de pouvoir être analysée.

Si vous souhaitez diffuser directement à partir d'un téléchargement d'URL dans un analyseur de diffusion (tel que GSON), essayez quelque chose dans ce sens. Commencez par obtenir un InputStream à partir de l'URL que vous essayez d'extraire:

    URL u = new URL(url);
    URLConnection conn = u.openConnection();
    InputStream is = new BufferedInputStream(conn.getInputStream());

Envoyez ensuite ce InputStream directement à votre analyseur de flux. Cela évitera d'avoir à extraire l'intégralité de la réponse en mémoire avant l'analyse, mais vous aurez tout de même besoin de suffisamment de mémoire pour contenir tous les objets créés par l'analyseur:

    GsonBuilder gb = new GsonBuilder(); // configure this as necessary
    Gson gson = gb.create();
    final Result response = gson.fromJson(
        new InputStreamReader(is, Charset.forName("UTF-8")),
        Result.class
    );

"Résultat" est une classe qui contiendra les données de la réponse JSON. Vous devrez vous assurer que tous les mappages fonctionnent pour vos données. Lisez donc GSON et faites ce qui vous convient le mieux.

Vous pouvez également utiliser GSON pour analyser les données JSON si vous les stockez dans un actif. Il suffit de lui remettre le flux d’entrée des données d’immobilisation et il fonctionne de la même manière.

2
Doug Stevenson

Essayez de préférence de casser l’objet Json en un objet plus petit et d’obtenir webService,

ou obtenir des données dans les parties et si vous ne pouvez pas le faire 

Vous devez utiliser un analyseur JSON en streaming. Pour Android, vous pouvez utiliser ces 2:

  1. GSON 

  2. Jackson

Le streaming GSON est expliqué à: https://sites.google.com/site/gson/streaming

Personnellement, j'aime bien Gson.

0
Cold Fire

La classe ApiUrlClass.Java suivante contient toutes les méthodes nécessaires. S'il vous plaît lire les commentaires de la classe que j'ai écrit. Cela vous aidera à faire ce dont vous avez besoin. Cela utilise également transparent.

import Android.graphics.Bitmap;
import Android.net.Uri;
import Android.os.Build;
import Android.util.Log;
import org.Apache.http.entity.mime.HttpMultipartMode;
import org.Apache.http.entity.mime.content.ByteArrayBody;
import org.Apache.http.entity.mime.content.ContentBody;
import org.Apache.http.entity.mime.content.StringBody;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import Java.io.BufferedReader;
import Java.io.BufferedWriter;
import Java.io.ByteArrayOutputStream;
import Java.io.FileNotFoundException;
import Java.io.IOException;
import Java.io.InputStream;
import Java.io.InputStreamReader;
import Java.io.OutputStream;
import Java.io.OutputStreamWriter;
import Java.net.HttpURLConnection;
import Java.net.SocketTimeoutException;
import Java.net.URL;
import Java.net.UnknownHostException;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLPeerUnverifiedException;

/*
Usage of the class

Create all the necessary API Call methods you need.
And either use a Thread or AsyncTask to call the following.

    JSONObject response = ApiUrlCalls.login("username", "passowrd");

After the response is obtained, check for status code like

    if(response.getInt("status_code") == 200){
        //TODO: code something
    } else {
        //TODO: code something
    }
*/

public class ApiUrlCalls {

    private String Host = "https://domain/path/"; //This will be concated with the function needed. Ref:1

    /*
        Now utilizing the method is so simple. Lets consider a login function, which sends username and password.
        See below for example.
    */

    public static JSONObject login(String username, String password){

        String functionCall = "login";
        Uri.Builder builder = new Uri.Builder()
                .appendQueryParameter("username", username)
                .appendQueryParameter("password", password);

        /*
            The return calls the apiPost method for processing.
            Make sure this should't happen in the UI thread, orelse, NetworkOnMainThread exception will be thrown.
        */
        return apiPost(builder, functionCall);

    }

    /*
        This method is the one which performs POST operation. If you need GET, just change it
        in like Connection.setRequestMethod("GET")
    */
    private static JSONObject apiPost(Uri.Builder builder, String function){
        try {
            int TIMEOUT = 15000;
            JSONObject jsonObject = new JSONObject();
            try {
                URL url = null;
                String response = "";

                /*
                    Ref:1
                    As mentioned, here below, in case the function is "login",
                    url looks like https://domain/path/login

                    This is generally a rewrited form by .htaccess in server.
                    If you need knowledge on RESTful API in PHP, refer 
                    http://stackoverflow.com/questions/34997738/creating-restful-api-what-kind-of-headers-should-be-put-out-before-the-response/35000332#35000332

                    I have answered how to create a RESTful API. It matches the above URL format, it also includes the .htaccess
                */

                url = new URL(Host + function);

                HttpsURLConnection conn = null;
                conn = (HttpsURLConnection) url.openConnection();
                assert conn != null;
                conn.setReadTimeout(TIMEOUT);
                conn.setConnectTimeout(TIMEOUT);
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);

                String query = builder.build().getEncodedQuery();

                OutputStream os = conn.getOutputStream();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
                writer.write(query);
                writer.flush();
                writer.close();
                os.close();
                conn.connect();


                int responseCode = conn.getResponseCode();
                String responseMessage = conn.getResponseMessage();
                jsonObject.put("status_code", responseCode);
                jsonObject.put("status_message", responseMessage);

                /*The if condition below will check if status code is greater than 400 and sets error status
                even before trying to read content, because HttpUrlConnection classes will throw exceptions
                for status codes 4xx and 5xx. You cannot read content for status codes 4xx and 5xx in HttpUrlConnection
                classes. 
                */

                if (jsonObject.getInt("status_code") >= 400) {
                    jsonObject.put("status", "Error");
                    jsonObject.put("msg", "Something is not good. Try again later.");
                    return jsonObject;
                }

                String line;
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));

                while ((line = br.readLine()) != null) {
                    response += line;
                }
                //Log.d("RESP", response);

                /*
                    After the actual payload is read as a string, it is time to change it into JSON.
                    Simply when it starts with "[" it should be a JSON array and when it starts with "{"
                    it is a JSONObject. That is what hapenning below.
                */
                if(response.startsWith("[")) {
                    jsonObject.put("content", new JSONArray(response));
                }
                if(response.startsWith("{")){
                    jsonObject.put("content", new JSONObject(response));
                }


            } catch(UnknownHostException e) {
            //No explanation needed :)
                jsonObject.put("status", "UnknownHostException");
                jsonObject.put("msg", "Check your internet connection");
            } catch (SocketTimeoutException){
            //This is when the connection timeouts. Timeouts can be modified by TIMEOUT variable above.
                jsonObject.put("status", "Timeout");
                jsonObject.put("msg", "Check your internet connection");
            } catch (SSLPeerUnverifiedException se) {
            //When an untrusted SSL Certificate is received, this happens. (Only for https.)
                jsonObject.put("status", "SSLException");
                jsonObject.put("msg", "Unable to establish secure connection.");
                se.printStackTrace();
            } catch (IOException e) {
            //This generally happens when there is a trouble in connection
                jsonObject.put("status", "IOException");
                jsonObject.put("msg", "Check your internet connection");
                e.printStackTrace();
            } catch(FileNotFoundException e){ 
            //There is no chance that this catch block will execute as we already checked for 4xx errors
                jsonObject.put("status", "FileNotFoundException");
                jsonObject.put("msg", "Some 4xx Error");
                e.printStackTrace();
            } catch (JSONException e){ 
            //This happens when there is a troble reading the content, or some notice or warnings in content, 
            //which generally happens while we modify the server side files. Read the "msg", and it is clear now :)
                jsonObject.put("status", "JSONException");
                jsonObject.put("msg", "We are experiencing a glitch, try back in sometime.");
                e.printStackTrace();
            } return jsonObject;

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

}
0
Sibidharan

Vous pouvez incorporer votre JSON dans le code de votre application comme vous l'avez suggéré, mais ce sera une mauvaise approche si le JSON est dynamique. Ensuite, vous devez envoyer une mise à jour pour votre application lorsque le JSON change.

Une meilleure solution consisterait à paginer le JSON que vous générez à partir de votre WebService, c’est-à-dire à le diviser en parties plus petites que vous pouvez extraire séquentiellement dans des appels d’API distincts.

0
Saraj Munjal