Utilizzo del file JSON nelle risorse dell'app Android


88

Supponiamo di avere un file con contenuti JSON nella cartella delle risorse non elaborate nella mia app. Come posso leggerlo nell'app, in modo da poter analizzare il JSON?

Risposte:


145

Vedi openRawResource . Qualcosa di simile dovrebbe funzionare:

InputStream is = getResources().openRawResource(R.raw.json_file);
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try {
    Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
    int n;
    while ((n = reader.read(buffer)) != -1) {
        writer.write(buffer, 0, n);
    }
} finally {
    is.close();
}

String jsonString = writer.toString();

1
E se volessi inserire la stringa in una risorsa String in Android e usarla dinamicamente utilizzando getResources (). GetString (R.String.name)?
Ankur Gautam

Per me non funziona a causa delle citazioni, che vengono ignorate durante la lettura e che sembrano non essere sfuggite
Marian Klühspies

1
C'è un modo per fare in modo che ButterKnife leghi la risorsa grezza? Scrivere più di 10 righe di codice solo per leggere una stringa sembra un po 'eccessivo.
Jezor

Come viene memorizzato il json all'interno delle risorse? Semplicemente dentro la \res\json_file.jsoncartella o dentro \res\raw\json_file.json?
Cliff Burton

1
Questa risposta manca di informazioni critiche. Dove si può getResources()chiamare? Dove dovrebbe andare il file di risorse raw? Quale convenzione dovresti seguire per assicurarti che gli strumenti di compilazione vengano creati R.raw.json_file?
NobodyMan

114

Kotlin è ora la lingua ufficiale per Android, quindi penso che sarebbe utile per qualcuno

val text = resources.openRawResource(R.raw.your_text_file)
                                 .bufferedReader().use { it.readText() }

Questa è un'operazione potenzialmente di lunga durata, quindi assicurati che venga richiamata dal thread principale!
Andrew Orobator

1
@AndrewOrobator Dubito che qualcuno metterebbe un grande json nelle risorse dell'app, ma sì, bel punto
Dima Rostopira

24

Ho usato la risposta di @ kabuko per creare un oggetto che viene caricato da un file JSON, utilizzando Gson , dalle risorse:

package com.jingit.mobile.testsupport;

import java.io.*;

import android.content.res.Resources;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;


/**
 * An object for reading from a JSON resource file and constructing an object from that resource file using Gson.
 */
public class JSONResourceReader {

    // === [ Private Data Members ] ============================================

    // Our JSON, in string form.
    private String jsonString;
    private static final String LOGTAG = JSONResourceReader.class.getSimpleName();

    // === [ Public API ] ======================================================

    /**
     * Read from a resources file and create a {@link JSONResourceReader} object that will allow the creation of other
     * objects from this resource.
     *
     * @param resources An application {@link Resources} object.
     * @param id The id for the resource to load, typically held in the raw/ folder.
     */
    public JSONResourceReader(Resources resources, int id) {
        InputStream resourceReader = resources.openRawResource(id);
        Writer writer = new StringWriter();
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(resourceReader, "UTF-8"));
            String line = reader.readLine();
            while (line != null) {
                writer.write(line);
                line = reader.readLine();
            }
        } catch (Exception e) {
            Log.e(LOGTAG, "Unhandled exception while using JSONResourceReader", e);
        } finally {
            try {
                resourceReader.close();
            } catch (Exception e) {
                Log.e(LOGTAG, "Unhandled exception while using JSONResourceReader", e);
            }
        }

        jsonString = writer.toString();
    }

    /**
     * Build an object from the specified JSON resource using Gson.
     *
     * @param type The type of the object to build.
     *
     * @return An object of type T, with member fields populated using Gson.
     */
    public <T> T constructUsingGson(Class<T> type) {
        Gson gson = new GsonBuilder().create();
        return gson.fromJson(jsonString, type);
    }
}

Per usarlo, dovresti fare qualcosa come il seguente (l'esempio è in un InstrumentationTestCase):

   @Override
    public void setUp() {
        // Load our JSON file.
        JSONResourceReader reader = new JSONResourceReader(getInstrumentation().getContext().getResources(), R.raw.jsonfile);
        MyJsonObject jsonObj = reader.constructUsingGson(MyJsonObject.class);
   }

3
Non dimenticare di aggiungere le dipendenze {compile com.google.code.gson: gson: 2.8.2 '} al tuo file
gradle

l'ultima versione di GSON èimplementation 'com.google.code.gson:gson:2.8.5'
Daniel

13

Da http://developer.android.com/guide/topics/resources/providing-resources.html :


File raw / arbitrari da salvare nella loro forma grezza. Per aprire queste risorse con un InputStream grezzo, chiama Resources.openRawResource () con l'ID risorsa, che è R.raw.filename.

Tuttavia, se hai bisogno di accedere ai nomi di file originali e alla gerarchia dei file, potresti considerare di salvare alcune risorse nella directory assets / (invece di res / raw /). Ai file negli asset / non viene assegnato un ID risorsa, quindi puoi leggerli solo utilizzando AssetManager.


5
Se voglio incorporare un file JSON nella mia app, dove dovrei metterlo? nella cartella degli asset o nella cartella raw? Grazie!
Ricardo

13

Come afferma @mah, la documentazione di Android ( https://developer.android.com/guide/topics/resources/providing-resources.html ) dice che i file json possono essere salvati nella directory / raw sotto / res (risorse) directory nel tuo progetto, ad esempio:

MyProject/
  src/ 
    MyActivity.java
  res/
    drawable/ 
        graphic.png
    layout/ 
        main.xml
        info.xml
    mipmap/ 
        icon.png
    values/ 
        strings.xml
    raw/
        myjsonfile.json

All'interno di un Activity, è possibile accedere al file json tramite la Rclasse (Resources) e leggere in una stringa:

Context context = this;
Inputstream inputStream = context.getResources().openRawResource(R.raw.myjsonfile);
String jsonString = new Scanner(inputStream).useDelimiter("\\A").next();

Questo utilizza la classe Java Scanner, portando a meno righe di codice rispetto ad altri metodi di lettura di un semplice file di testo / json. Il modello delimitatore \Asignifica "l'inizio dell'input". .next()legge il token successivo, che in questo caso è l'intero file.

Esistono diversi modi per analizzare la stringa json risultante:


1
questa dovrebbe essere la risposta accettata, solo due righe e fatto.Grazie
Ashana.Jackol

esigenzeimport java.util.Scanner; import java.io.InputStream; import android.content.Context;
AndrewHarvey

4
InputStream is = mContext.getResources().openRawResource(R.raw.json_regions);
                            int size = is.available();
                            byte[] buffer = new byte[size];
                            is.read(buffer);
                            is.close();
                           String json = new String(buffer, "UTF-8");

1

Utilizzando:

String json_string = readRawResource(R.raw.json)

Funzioni:

public String readRawResource(@RawRes int res) {
    return readStream(context.getResources().openRawResource(res));
}

private String readStream(InputStream is) {
    Scanner s = new Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}

0

Ho trovato questa risposta dello snippet di Kotlin molto utile ♥ ️

Mentre la domanda originale chiedeva di ottenere una stringa JSON, immagino che alcuni potrebbero trovarlo utile. Un ulteriore passo avanti Gsonporta a questa piccola funzione di tipo reificato:

private inline fun <reified T> readRawJson(@RawRes rawResId: Int): T {
    resources.openRawResource(rawResId).bufferedReader().use {
        return gson.fromJson<T>(it, object: TypeToken<T>() {}.type)
    }
}

Nota che vuoi usare TypeTokennon solo T::classcosì se leggi un fileList<YourType> non perderai il tipo per cancellazione del tipo.

Con l'inferenza del tipo puoi quindi usare in questo modo:

fun pricingData(): List<PricingData> = readRawJson(R.raw.mock_pricing_data)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.