Korzystanie z pliku JSON w zasobach aplikacji na Androida

87

Załóżmy, że mam plik z zawartością JSON w folderze surowych zasobów w mojej aplikacji. Jak mogę to wczytać do aplikacji, aby przeanalizować JSON?

yydl
źródło

Odpowiedzi:

143

Zobacz openRawResource . Coś takiego powinno działać:

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();
kabuko
źródło
1
Co jeśli chcę umieścić ciąg w zasobie typu String w systemie Android i używać go dynamicznie za pomocą metody getResources (). GetString (R.String.name)?
Ankur Gautam
Dla mnie to nie działa z powodu cytatów, które są ignorowane podczas czytania i które również wydają się nie do
uniknięcia
1
Czy jest jakiś sposób, aby ButterKnife wiązał surowiec? Napisanie ponad 10 linii kodu tylko po to, aby odczytać ciąg, wydaje się trochę przesadą.
Jezor,
W jaki sposób plik JSON jest przechowywany w zasobach? Po prostu w \res\json_file.jsonfolderze czy w środku \res\raw\json_file.json?
Cliff Burton
W tej odpowiedzi brakuje krytycznych informacji. Gdzie można getResources()zadzwonić? Gdzie powinien znajdować się surowy plik zasobów? Jakiej konwencji należy przestrzegać, aby narzędzia kompilacji tworzyły R.raw.json_file?
NobodyMan
112

Kotlin jest teraz oficjalnym językiem Androida, więc myślę, że przydałoby się to komuś

val text = resources.openRawResource(R.raw.your_text_file)
                                 .bufferedReader().use { it.readText() }
Dima Rostopira
źródło
Jest to potencjalnie długotrwała operacja, więc upewnij się, że została odwołana z głównego wątku!
Andrew Orobator
@AndrewOrobator Wątpię, czy ktoś umieściłby duży json w zasobach aplikacji, ale tak, fajna uwaga
Dima Rostopira
24

Użyłem odpowiedzi @ kabuko, aby utworzyć obiekt, który ładuje się z pliku JSON, używając Gson , z zasobów:

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);
    }
}

Aby go użyć, wykonaj coś podobnego do następującego (przykład jest w 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);
   }
jwir3
źródło
3
Nie zapomnij dodać zależności {compile com.google.code.gson: gson: 2.8.2 '} do swojego pliku
gradle
ostatnia wersja GSON toimplementation 'com.google.code.gson:gson:2.8.5'
Daniel
12

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

surowe /
dowolne pliki do zapisania w ich postaci surowej. Aby otworzyć te zasoby za pomocą surowego InputStream, wywołaj Resources.openRawResource () z identyfikatorem zasobu, którym jest R.raw.filename.

Jeśli jednak potrzebujesz dostępu do oryginalnych nazw plików i hierarchii plików, możesz rozważyć zapisanie niektórych zasobów w katalogu asset / (zamiast res / raw /). Pliki w zasobach / nie mają identyfikatora zasobu, więc możesz je odczytać tylko za pomocą AssetManager.

mah
źródło
5
Jeśli chcę osadzić plik JSON w mojej aplikacji, gdzie powinienem go umieścić? w folderze zasobów czy w folderze surowym? Dzięki!
Ricardo
12

Podobnie jak w przypadku @mah, dokumentacja Androida ( https://developer.android.com/guide/topics/resources/providing-resources.html ) mówi, że pliki json mogą być zapisywane w katalogu / raw w katalogu / res (zasoby) katalog w Twoim projekcie, na przykład:

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

Wewnątrz Activitypliku json można uzyskać dostęp za pośrednictwem Rklasy (Resources) i odczytać go w ciągu:

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

Wykorzystuje klasę Java Scanner, co prowadzi do mniejszej liczby wierszy kodu niż niektóre inne metody odczytu prostego pliku tekstowego / json. Wzorzec separatora \Aoznacza „początek danych wejściowych”. .next()czyta następny token, którym w tym przypadku jest cały plik.

Istnieje wiele sposobów analizowania wynikowego ciągu JSON:

ʕ ᵔᴥᵔ ʔ
źródło
1
to powinna być zaakceptowana odpowiedź, tylko dwie linijki i gotowe. Dzięki
Ashana.Jackol
potrzebyimport 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");
NickUnuchek
źródło
1

Za pomocą:

String json_string = readRawResource(R.raw.json)

Funkcje:

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() : "";
}
Mahdi Astanei
źródło
0

Znaleziona odpowiedź fragmentu Kotlin jest bardzo pomocna ♥ ️

Podczas gdy pierwotne pytanie zadane w celu uzyskania ciągu JSON, wydaje mi się, że niektórzy mogą uznać to za przydatne. Krok dalej Gsonprowadzi do tej małej funkcji w typie zreifikowanym:

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

Zauważ, że chcesz użyć TypeTokennie tylko, T::classwięc jeśli przeczytasz List<YourType>, nie stracisz wymazywania typu po typie.

Z wnioskiem o typie możesz użyć w następujący sposób:

fun pricingData(): List<PricingData> = readRawJson(R.raw.mock_pricing_data)
themightyjon
źródło