Utilisation du fichier JSON dans les ressources d'applications Android

87

Supposons que j'ai un fichier avec du contenu JSON dans le dossier des ressources brutes de mon application. Comment puis-je lire cela dans l'application, afin de pouvoir analyser le JSON?

yydl
la source

Réponses:

143

Voir openRawResource . Quelque chose comme ça devrait fonctionner:

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
la source
1
Que faire si je veux mettre la chaîne dans une ressource String dans Android et l'utiliser dynamiquement en utilisant getResources (). GetString (R.String.name)?
Ankur Gautam
Pour moi, cela ne fonctionne pas à cause des citations, qui sont ignorées lors de la lecture et qui semblent également ne pas pouvoir être échappées
Marian Klühspies
1
Existe-t-il un moyen de faire en sorte que ButterKnife lie la ressource brute? Écrire plus de 10 lignes de code juste pour lire une chaîne semble un peu exagéré.
Jezor
Comment le json est-il stocké dans les ressources? Simplement à l'intérieur du \res\json_file.jsondossier ou à l'intérieur \res\raw\json_file.json?
Cliff Burton
Cette réponse manque d'informations critiques. Où peut getResources()être appelé? Où doit aller le fichier de ressources brutes? Quelle convention devez-vous suivre pour vous assurer que les outils de construction créent R.raw.json_file?
NobodyMan
112

Kotlin est maintenant la langue officielle pour Android, donc je pense que ce serait utile pour quelqu'un

val text = resources.openRawResource(R.raw.your_text_file)
                                 .bufferedReader().use { it.readText() }
Dima Rostopira
la source
Il s'agit d'une opération potentiellement longue, alors assurez-vous qu'elle est appelée hors du thread principal!
Andrew Orobator
@AndrewOrobator Je doute que quelqu'un mettrait de gros json dans les ressources de l'application, mais oui, bon point
Dima Rostopira
24

J'ai utilisé la réponse de @ kabuko pour créer un objet qui se charge à partir d'un fichier JSON, en utilisant Gson , à partir des ressources:

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

Pour l'utiliser, vous feriez quelque chose comme ce qui suit (l'exemple est dans 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);
   }
jwir3
la source
3
N'oubliez pas d'ajouter les dépendances {compile com.google.code.gson: gson: 2.8.2 '} à votre fichier
gradle
La dernière version de GSON estimplementation 'com.google.code.gson:gson:2.8.5'
Daniel
12

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


Fichiers bruts / arbitraires à enregistrer sous leur forme brute. Pour ouvrir ces ressources avec un InputStream brut, appelez Resources.openRawResource () avec l'ID de ressource, qui est R.raw.filename.

Cependant, si vous avez besoin d'accéder aux noms de fichiers d'origine et à la hiérarchie des fichiers, vous pouvez envisager d'enregistrer certaines ressources dans le répertoire assets / (au lieu de res / raw /). Les fichiers des assets / ne reçoivent pas d'ID de ressource, vous ne pouvez donc les lire qu'à l'aide d'AssetManager.

mah
la source
5
Si je souhaite intégrer un fichier JSON dans mon application, où dois-je le mettre? dans le dossier des actifs ou le dossier brut? Merci!
Ricardo
12

Comme les états @mah, la documentation Android ( https://developer.android.com/guide/topics/resources/providing-resources.html ) indique que les fichiers json peuvent être enregistrés dans le répertoire / raw sous le / res (ressources) répertoire de votre projet, par exemple:

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

Dans un Activity, le fichier json est accessible via la Rclasse (Resources) et lu dans une chaîne:

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

Cela utilise la classe Java Scanner, ce qui entraîne moins de lignes de code que certaines autres méthodes de lecture d'un simple fichier texte / json. Le motif de délimitation \Asignifie «le début de l'entrée». .next()lit le jeton suivant, qui est le fichier entier dans ce cas.

Il existe plusieurs façons d'analyser la chaîne json résultante:

ʕ ᵔᴥᵔ ʔ
la source
1
cela devrait être la réponse acceptée, juste deux lignes et terminé.Merci
Ashana.Jackol
besoinsimport 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
la source
1

En utilisant:

String json_string = readRawResource(R.raw.json)

Les fonctions:

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
la source
0

J'ai trouvé cette réponse d'extrait de code Kotlin très utileJ'ai ♥ ️

Alors que la question d'origine demandait d'obtenir une chaîne JSON, je pense que certains pourraient trouver cela utile. Un pas de plus avec Gsonconduit à cette petite fonction de type réifié:

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

Notez que vous ne souhaitez pas utiliser TypeTokenuniquement T::classsi vous lisez unList<YourType> vous ne perdrez pas le type par type d'effacement.

Avec l'inférence de type, vous pouvez ensuite utiliser comme ceci:

fun pricingData(): List<PricingData> = readRawJson(R.raw.mock_pricing_data)
themightyjon
la source