Como Leer un archivo JSON en Android (Android Studio 3.6.1 + Java) – Parte 1

Demo

El formato JSON es uno de los más usados en el intercambio y las gestiones de datos, son ligeros, dinámicos y mejoran el rendimiento de las aplicación en diferentes entornos, si tienes datos en formato JSON, ya sea en un archivo local o desde una API REST y deseas leerlos en Android, en este Post te enseñare como hacerlo, vamos con ello.

Partes

  • Parte 1
  • Parte 2 (Final – Demo, Código Fuente en GitHub)

Antes de continuar te invito a leer los siguientes artículos:

Y también te invito a escuchar el Podcast: “Dominio del trabajo con Varios Lenguajes de Programación”:

Spotify SoundCloud

Bien ahora continuemos con el Post: Como Leer un archivo JSON en Android (Android Studio 3.6.1 + Java) – Parte 1 

Creando un Nuevo Proyecto

Empezamos creando un nuevo proyecto, seleccionamos Empty Activity (Actividad Vacía) y luego presionamos el botón Next para continuar.

Paso seguido le doy un nombre a mi proyecto, yo le pondré de nombre MiApp, tu le puedes poner el nombre que desees. Presiono el botón Finish para terminar de crear el nuevo proyecto.

Bien ahora pasemos a crear el código y los demás elementos para poder leer el archivo JSON.

Archivo AndroidManifest.xml

Voy al archivo AndroidManifest.xml que encuentra en app > manifest > AndroidManifest.xml y lo abro.

/app
├── /manifests
    ├── AndroidManifest.xml // Abro este Archivo 
├── /java
├── /res
/Gradle Scripts

En el archivo AndroidManifest.xml voy a tener el siguiente contenido, solo añado el permiso para que mi aplicación pueda usar Internet, el resto lo dejo tal como estaba.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.miapp">

    <!-- Permiso para que mi App use Internet --> 
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Bueno ahora pasaremos a crear la actividad principal con los métodos y elementos necesarios para la aplicación.

Actividad Principal (MainActivity)

Abro el archivo MainActivity.java que se encuentra en app > java > com.example.miapp > MainActivity

/app
├── /manifests
├── /java
    ├── /com.example.miapp 
        ├── MainActivity // Abro este Archivo 
    ├── /com.example.miapp (androidTest)
    ├── /com.example.miapp (test)  
├── /res
/Gradle Scripts

En el archivo MainActivity.java realizo las siguientes importaciones antes de la clase MainActivity.

package com.example.miapp;

import androidx.appcompat.app.AppCompatActivity;

import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.annotation.SuppressLint;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.Toast;

import com.example.miapp.adaptadores.MyAppAdapter;
import com.example.miapp.modelos.MyAppModel;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap; 

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

Paso seguido antes del método onCreate que esta dentro de la clase MainActivity creo la variable datos en donde recibo los datos del archivo JSON, creo una variable codigodatos con valor 1 la cual me servirá para manejar el estado de la carga de datos, luego declaro un RecyclerView que es en donde cargaré los datos, también llamo a mi modelo MyAppModel, llamo a mi adaptador MyAppAdapter y por ultimo declaro un ProgressDialog el cual me aparecerá antes de listar los datos en el RecyclerView.

Y dentro del método onCreate() instancio o llamo al layout para el RecyclerView y también llamo al método leerJSON() el cual lo crearé a continuación.

public class MainActivity extends AppCompatActivity {

    private String datos = "https://nubecolectiva.com/blog/tutos/demos/leer_json_android_java/datos/postres.json";
    private final int codigodatos = 1;
    private RecyclerView recyclerView;
    ArrayList<MyAppModel> myappModelArrayList;
    private MyAppAdapter myappAdapter;  

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Llamo al layout para el RecyclerView
        recyclerView = findViewById(R.id.contenedor);

        // Llamo al método para leer el archivo JSON (Este método lo crearé a continuación)
        leerJSON();       

    }

}

La creación del modelo MyAppModel y el adaptador MyAppAdapter lo haré más adelante, vamos por pasos para mantener el orden.

Ahora en mi método leerJSON() agrego lo siguiente (He colocado comentarios en el código para explicar que hace cada porción de código).

@SuppressLint("StaticFieldLeak")
private void leerJSON(){

    // Inicio una tare Asíncrona
    new AsyncTask<Void, Void, String>(){

        // La tarea se llevará acabo de fondo
        protected String doInBackground(Void[] params) {

            String response = "";

            // Declaro un HashMap
            HashMap<String, String> map = new HashMap<>();

            // Hago la petición de los datos
            try {
                HttpRequest req = new HttpRequest(datos);
                response = req.prepare(HttpRequest.Method.POST).reciboDatos(map).enviaryRecibirString();
            } catch (Exception e) {
                response = e.getMessage();
            }
            return response;
        }

        // Después de realizar la petición de los datos, llamo al método tareaCompletada()
        // El método tareaCompletada() lo crearé a continuación
        protected void onPostExecute(String resultado) {
            tareaCompletada(resultado, codigodatos);
        }

    }.execute();
}

En mi método tareaCompletada() agrego lo siguiente (He colocado comentarios en el código para explicar que hace cada porción de código).

public void tareaCompletada(String response, int serviceCode) {
    switch (serviceCode) {

        // Uso un case y le paso la variable 'codigodatos'
        case codigodatos:

            // Verifico si los datos se recibieron con el método siCorrecto()
            // El método siCorrecto() lo crearé más adelante.
            if (siCorrecto(response)) {

                // A mi modelo le paso el método obtenerInformacion(), este método lo crearé más adelante.
                myappModelArrayList = obtenerInformacion(response);

                // A mi Adaptador le paso mi modelo
                myappAdapter = new MyAppAdapter(this,myappModelArrayList);

                // Le paso mi adaptador al RecyclerView
                recyclerView.setAdapter(myappAdapter);

                // Cargo el Layout del RecyclerView
                recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false));

            }else {
                // Si hubo error, lo muestro en un Toast
                Toast.makeText(MainActivity.this, obtenerCodigoError(response), Toast.LENGTH_SHORT).show();
            }
    }
}

Para mi método obtenerInformacion() agrego lo siguiente (He colocado comentarios en el código para explicar que hace cada porción de código).

public ArrayList<MyAppModel> obtenerInformacion(String response) {

    // Creo un array con los datos JSON que he obtenido
    ArrayList<MyAppModel> listaArray = new ArrayList<>();

    // Solicito los datos al archivo JSON
    try {
        JSONObject jsonObject = new JSONObject(response);

        // En los datos que recibo verifico si obtengo el estado o 'status' con el valor 'true'
        // El dato 'status' con el valor 'true' se encuentra dentro del archivo JSON
        if (jsonObject.getString("status").equals("true")) {

            // Accedo a la fila 'postres' del archivo JSON
            JSONArray dataArray = jsonObject.getJSONArray("postres");

            // Recorro los datos que hay en la fila 'postres' del archivo JSON
            for (int i = 0; i < dataArray.length(); i++) {

                // Creo la variable 'datosModelo' y le paso mi modelo 'MyAppModel'
                MyAppModel datosModelo = new MyAppModel();

                // Creo la  variable 'objetos' y recupero los valores
                JSONObject objetos = dataArray.getJSONObject(i);

                // Selecciono dato por dato
                datosModelo.setNombre(objetos.getString("nombre"));
                datosModelo.setPrecio(objetos.getString("precio"));
                datosModelo.setStock(objetos.getString("stock"));
                datosModelo.setImagen(objetos.getString("amp-img"));

                // Meto los datos en el array que definí más arriba 'listaArray'
                listaArray.add(datosModelo);

            }
        }

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

    // Devuelvo el array con los datos del archivo JSON
    return listaArray;
}

Dentro del método tareaCompletada() llame al método siCorrecto(), vamos a definir el contenido de este método, creo el método y agrego lo siguiente (He colocado comentarios en el código para explicar que hace cada porción de código).

public boolean siCorrecto(String response) {

    // Verificamos si la petición de los datos ha sido correcta
    try {

        // Creo la variable 'objetoJson' de tipo JSONObjetc (Objeto JSON) y le
        // paso los datos que he recibido (response)
        JSONObject objetoJson = new JSONObject(response);

        // En los datos que he recibido verifico si obtengo el estado o 'status' con el valor 'true'
        // El dato 'status' con el valor 'true' se encuentra dentro del archivo JSON
        if (objetoJson.optString("status").equals("true")) {

            return true; // Retorno 'true' si es correcto

        } else {

            return false; // Retorno 'false' si es correcto
        }

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

    // Si nada se lleva acabo retorno 'false'
    return false;
}

Por último crearé el método obtenerCodigoError() el cual llamo en mi método tareaCompletada() (He colocado comentarios en el código para explicar que hace cada porción de código).

public String obtenerCodigoError(String response) {

    // Solicitamos el código de error que se encuentra en el archivo JSON
    try {
        // El archivo JSON contiene el dato 'message'
        JSONObject jsonObject = new JSONObject(response);

        return jsonObject.getString("message");

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

    // Si no hay datos en el archiv JSON, muestro un mensaje
    return "No hay datos";
}

A continuación, todo el código del archivo MainActivity.java (Actividad Principal), este código también lo puedes encontrar en el repositorio GitHub.

package com.example.miapp;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.annotation.SuppressLint;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.Toast;

import com.example.miapp.adaptadores.MyAppAdapter;
import com.example.miapp.modelos.MyAppModel;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;

public class MainActivity extends AppCompatActivity {

    private String datos = "https://nubecolectiva.com/blog/tutos/demos/leer_json_android_java/datos/postres.json";
    private final int codigodatos = 1;
    private RecyclerView recyclerView;
    ArrayList<MyAppModel> myappModelArrayList;
    private MyAppAdapter myappAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Llamo al layout para el RecyclerView
        recyclerView = findViewById(R.id.contenedor);

        // Llamo al método para leer el archivo JSON (Este método lo crearé a continuación)
        leerJSON();
    }

    @SuppressLint("StaticFieldLeak")
    private void leerJSON(){

        // Inicio una tare Asíncrona
        new AsyncTask<Void, Void, String>(){

            // La tarea se llevará acabo de fondo
            protected String doInBackground(Void[] params) {

                String response = "";

                // Declaro un HashMap
                HashMap<String, String> map = new HashMap<>();

                // Hago la petición de los datos
                try {
                    HttpRequest req = new HttpRequest(datos);
                    response = req.prepare(HttpRequest.Method.POST).reciboDatos(map).enviaryRecibirString();
                } catch (Exception e) {
                    response = e.getMessage();
                }
                return response;
            }

            // Después de realizar la petición de los datos, llamo al método tareaCompletada()
            // El método tareaCompletada() lo crearé a continuación
            protected void onPostExecute(String resultado) {
                tareaCompletada(resultado, codigodatos);
            }

        }.execute();
    }

    public void tareaCompletada(String response, int serviceCode) {
        switch (serviceCode) {

            // Uso un case y le paso la variable 'codigodatos'
            case codigodatos:

                // Verifico si los datos se recibieron con el método siCorrecto()
                // El método siCorrecto() lo crearé más adelante.
                if (siCorrecto(response)) {

                    // A mi modelo le paso el método obtenerInformacion(), este método lo crearé más adelante.
                    myappModelArrayList = obtenerInformacion(response);

                    // A mi Adaptador le paso mi modelo
                    myappAdapter = new MyAppAdapter(this,myappModelArrayList);

                    // Le paso mi adaptador al RecyclerView
                    recyclerView.setAdapter(myappAdapter);

                    // Cargo el Layout del RecyclerView
                    recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false));

                }else {
                    // Si hubo error, lo muestro en un Toast
                    Toast.makeText(MainActivity.this, obtenerCodigoError(response), Toast.LENGTH_SHORT).show();
                }
        }
    }

    public ArrayList<MyAppModel> obtenerInformacion(String response) {

        // Creo un array con los datos JSON que he obtenido
        ArrayList<MyAppModel> listaArray = new ArrayList<>();

        // Solicito los datos al archivo JSON
        try {
            JSONObject jsonObject = new JSONObject(response);

            // En los datos que recibo verifico si obtengo el estado o 'status' con el valor 'true'
            // El dato 'status' con el valor 'true' se encuentra dentro del archivo JSON
            if (jsonObject.getString("status").equals("true")) {

                // Accedo a la fila 'postres' del archivo JSON
                JSONArray dataArray = jsonObject.getJSONArray("postres");

                // Recorro los datos que hay en la fila 'postres' del archivo JSON
                for (int i = 0; i < dataArray.length(); i++) {

                    // Creo la variable 'datosModelo' y le paso mi modelo 'MyAppModel'
                    MyAppModel datosModelo = new MyAppModel();

                    // Creo la  variable 'objetos' y recupero los valores
                    JSONObject objetos = dataArray.getJSONObject(i);

                    // Selecciono dato por dato
                    datosModelo.setNombre(objetos.getString("nombre"));
                    datosModelo.setPrecio(objetos.getString("precio"));
                    datosModelo.setStock(objetos.getString("stock"));
                    datosModelo.setImagen(objetos.getString("amp-img"));

                    // Meto los datos en el array que definí más arriba 'listaArray'
                    listaArray.add(datosModelo);

                }
            }

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

        // Devuelvo el array con los datos del archivo JSON
        return listaArray;
    }

    public boolean siCorrecto(String response) {

        // Verificamos si la petición de los datos ha sido correcta
        try {

            // Creo la variable 'objetoJson' de tipo JSONObjetc (Objeto JSON) y le
            // paso los datos que he recibido (response)
            JSONObject objetoJson = new JSONObject(response);

            // En los datos que he recibido verifico si obtengo el estado o 'status' con el valor 'true'
            // El dato 'status' con el valor 'true' se encuentra dentro del archivo JSON
            if (objetoJson.optString("status").equals("true")) {

                return true; // Retorno 'true' si es correcto

            } else {

                return false; // Retorno 'false' si es correcto
            }

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

        // Si nada se lleva acabo retorno 'false'
        return false;
    }

    public String obtenerCodigoError(String response) {

        // Solicitamos el código de error que se encuentra en el archivo JSON
        try {
            // El archivo JSON contiene el dato 'message'
            JSONObject jsonObject = new JSONObject(response);

            return jsonObject.getString("message");

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

        // Si no hay datos en el archiv JSON, muestro un mensaje
        return "No hay datos";
    }

}

Bien hasta aquí esta primera parte, hemos creado el proyecto, configurado el archivo AndroidManifest.xml y creado el código de la actividad principal en el archivo MainActivity.java

Ten Paciencia, lo que quiero es que entiendas todo el proceso de como crear la aplicación y no llenarte el capitulo de mucho contenido porque te puedes marear y no tendrás un óptimo aprendizaje. 

Nota(s)

  • En la siguiente Parte continuaremos con la creación del Modelo, el Adaptador y otros elementos que son necesarios para que la aplicación funcione.
  • No olvides que debemos usar la Tecnología para hacer cosas Buenas por el Mundo. 

Síguenos en nuestras Redes Sociales para que no te pierdas nuestros próximos contenidos.