在Android App资源中使用JSON文件


87

假设我的应用程序的原始资源文件夹中有一个包含JSON内容的文件。如何将其读入应用程序,以便解析JSON?

Answers:


143

参见openRawResource。这样的事情应该起作用:

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
如果我要将字符串放入android的String资源中,并通过getResources()。getString(R.String.name)动态使用它怎么办?
Ankur Gautam 2014年

对我来说,由于引号而无法使用,引号在阅读时会被忽略,而且似乎也无法逃脱
玛丽安·克鲁斯派(MarianKlühspies)2014年

1
有什么方法可以使ButterKnife绑定原始资源?仅仅为了读取一个字符串而编写10余行代码似乎有点过大。
Jezor '16

json如何存储在资源中?只是在\res\json_file.json文件夹内还是内部\res\raw\json_file.json
克里夫·伯顿

该答案缺少关键信息。在哪里可以getResources()叫?原始资源文件应该放在哪里?您应遵循哪些约定以确保构建工具能够创建R.raw.json_file
NobodyMan '18

112

Kotlin现在是Android的官方语言,所以我认为这对某人很有用

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

这是一个可能长时间运行的操作,因此请确保从主线程中调用该操作!
Andrew Orobator

@AndrewOrobator我怀疑有人会在应用程序资源中放入大json,但是的,很高兴
Dima Rostopira

24

我使用@kabuko的答案创建了一个对象,该对象使用Gson从JSON文件从JSON文件加载:

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

要使用它,您需要执行以下操作(示例位于中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
不要忘记将依赖项{compile com.google.code.gson:gson:2.8.2'}添加到gradle文件中
patrics

GSON的最新版本是implementation 'com.google.code.gson:gson:2.8.5'
Daniel

12

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

raw /
任意文件以原始格式保存。要使用原始InputStream打开这些资源,请调用带有资源ID(即R.raw.filename)的Resources.openRawResource()。

但是,如果需要访问原始文件名和文件层次结构,则可以考虑将一些资源保存在资产/目录中(而不是res / raw /)。没有给Assets /中的文件提供资源ID,因此您只能使用AssetManager读取它们。


5
如果我想在应用程序中嵌入JSON文件,应该放在哪里?在资产文件夹还是原始文件夹中?谢谢!
里卡多

12

像@mah一样,Android文档(https://developer.android.com/guide/topics/resources/providing-resources.html)表示json文件可能保存在/ res(资源)下的/ raw目录中。项目中的目录,例如:

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

在内Activity,可以通过R(Resources)类访问json文件,并将其读取为String:

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

它使用Java类Scanner,比其他一些读取简单text / json文件的方法所需要的代码更少。分隔符模式\A表示“输入的开始”。.next()读取下一个标记,在这种情况下为整个文件。

有多种方法可以解析生成的json字符串:

  • 使用内置于JSONObjectJSONArray对象中的Java / Android ,如下所示:Android / Java中的JSON Array迭代。这可能是方便使用来获得字符串,整数等等optString(String name)optInt(String name)等等方法,而不是getString(String name)getInt(String name)方法,因为opt方法失败的情况下返回null而不是一个异常的。
  • 使用Java / Android json序列化/反序列化库,就像这里提到的那样:https ://medium.com/@IlyaEremin/android-json-parsers-comparison-2017-8b5221721e31

1
这应该是公认的答案,只需完成两行即可。谢谢
Ashana.Jackol '19

需求import 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

使用:

String json_string = readRawResource(R.raw.json)

职能:

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

发现这个科特林片段答案非常有帮助♥️

虽然最初的问题要求获取JSON字符串,但我认为有些人可能会觉得这很有用。更进一步的步骤将Gson导致此小功能带有化类型:

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

请注意,您不仅要使用TypeTokenT::class所以如果您阅读a字List<YourType>,就不会因逐字删除而丢失字。

通过类型推断,您可以像这样使用:

fun pricingData(): List<PricingData> = readRawJson(R.raw.mock_pricing_data)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.