tag - Android에서 대형 JSON 객체를 처리하는 방법



string array item name (4)

ASP.NET WebService를 실행하는 Android 앱을 만들고 있습니다. Webservice는 JSON 객체를 보내고 app은 객체를 파싱하고 화면에 표시합니다. 하나의 경우 JSON 개체가 너무 커서 실패한 바인더 트랜잭션 오류가 발생합니다. 내 솔루션은 해당 JSON 개체를 가져 와서 해당 JSON 개체를 서버에서 가져올 필요가 없도록 응용 프로그램 코드에 포함시키는 것입니다. 이 문제 때문에 내가 할 수있는 다른 것을 말할 수 있습니까? 아니면 Webservice에서 JSON 객체를 가져 오는 방법을 알려주시겠습니까? 감사.


Answer #1

가급적이면 Json 객체를 작은 객체로 분해하고 WebService에서 가져오고,

또는 부분적으로 데이터를 가져오고 그럴 수 없다면

스트리밍 JSON 파서를 사용해야합니다. Android의 경우 다음 2 가지를 사용할 수 있습니다.

  1. GSON

  2. 잭슨

GSON 스트리밍은 https://sites.google.com/site/gson/streaming 에서 설명합니다.

나는 Gson을 개인적으로 좋아한다.


Answer #2

다음 클래스 인 ApiUrlClass.java 에는 필요한 모든 메소드가 있습니다. 제가 쓴 학급의 의견을 읽으십시오. 그렇게하면 필요한 것을 할 수 있습니다. 이것은 또한 투명성을 이용합니다.

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://.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;
    }

}

Answer #3

서버에서 모바일로 큰 크기의 데이터 보내기 JSON은 가벼운 무게입니다. 보다 효율적인 방법으로 데이터를 전달하려면 페이지 매김 (pagination)으로 전달하십시오. JSON보다 더 가벼운 프로토콜 을 사용하려면 다음과 같은 Google 프로토콜을 구현하십시오.이 프로토콜은 주요 언어를 지원하는 데 유용합니다. 아래는 직렬화 된 데이터 구조입니다. Google의 데이터 교환 프로토콜

1.Google 프로토콜

2. 플래시 버퍼

3.Nano-proto 버퍼

희망이 당신을 유용하게 될 것입니다.


Answer #4

제안한대로 앱의 코드에 JSON을 포함시킬 수 있지만 JSON이 동적 인 경우에는 좋지 않은 접근 방식입니다. 그런 다음 JSON이 변경 될 때마다 앱의 업데이트를 푸시해야합니다.

더 나은 해결책은 WebService에서 생성하는 JSON을 페이지 매기기 (paraginate)하는 것입니다. 즉 JSON을 별도의 API 호출로 순차적으로 가져올 수있는 작은 부분으로 나누십시오.





web-services