在 Android 应用资源中使用 JSON 文件

Posted

技术标签:

【中文标题】在 Android 应用资源中使用 JSON 文件【英文标题】:Using JSON File in Android App Resources 【发布时间】:2011-09-15 00:56:19 【问题描述】:

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

【问题讨论】:

注意 - 现在这个问题已经有 10 年历史了,最佳答案并不好。一定要向下滚动到正确的答案。这只是一行代码。 如何读取源 XML 文件的内容? 【参考方案1】:

见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();

【讨论】:

如果我想将字符串放在android的String资源中并使用getResources().getString(R.String.name)动态使用它怎么办? 对我来说它不起作用,因为引号,在阅读时会被忽略,而且似乎也无法转义 有没有办法让ButterKnife绑定原始资源?仅仅为了读取一个字符串而编写 10 多行代码似乎有点过头了。 资源里面的json是怎么存储的?只是在\res\json_file.json 文件夹内或\res\raw\json_file.json 内? 这个答案缺少关键信息。在哪里可以调用getResources()?原始资源文件应该放在哪里?您应该遵循什么约定来确保构建工具创建 R.raw.json_file【参考方案2】:

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

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

【讨论】:

这是一个可能需要长时间运行的操作,因此请确保从主线程中调用它! @AndrewOrobator 我怀疑有人会将大 json 放入应用程序资源中,但是是的,很好【参考方案3】:

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

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

【讨论】:

不要忘记将依赖项 compile com.google.code.gson:gson:2.8.2' 添加到您的 gradle 文件中 GSON 的最新版本是implementation 'com.google.code.gson:gson:2.8.5'【参考方案4】:

像@mah 所说,Android 文档 (https://developer.android.com/guide/topics/resources/providing-resources.html) 说 json 文件可能会保存在项目中 /res (resources) 目录下的 /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(资源)类访问json文件,并读取到字符串:

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

这使用Java 类Scanner,与其他读取简单文本/json 文件的方法相比,代码行数更少。分隔符模式\A 表示“输入的开头”。 .next() 读取下一个令牌,在这种情况下是整个文件。

解析生成的json字符串有多种方式:

使用 Java / Android 内置的 JSONObject 和 JSONArray 对象,例如:JSON Array iteration in Android/Java。使用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

【讨论】:

这应该是公认的答案,只需两行就完成了。谢谢 需要import java.util.Scanner; import java.io.InputStream; import android.content.Context; 谢谢,好东西。不幸的是,操作系统对像这样的非常古老的问题有一些非常古老、完全错误的答案。【参考方案5】:

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

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

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

【讨论】:

如果我想在我的应用程序中嵌入一个 JSON 文件,我应该把它放在哪里?在资产文件夹或原始文件夹中?谢谢!【参考方案6】:
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");

【讨论】:

【参考方案7】:

找到this Kotlin snippet answer very helpful♥️

虽然最初的问题要求获取 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)
    

请注意,您要使用TypeToken 而不仅仅是T::class,因此如果您阅读List&lt;YourType&gt;,您不会因类型擦除而丢失类型。

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

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

【讨论】:

【参考方案8】:

使用:

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() : "";

【讨论】:

以上是关于在 Android 应用资源中使用 JSON 文件的主要内容,如果未能解决你的问题,请参考以下文章

Android 如何引用本地json文件

在 Fragments 中使用 JSON 时,应用在 Android 开发中没有响应

(网络数据交互)Android解析Internet的Json资源文件

Android读取assets目录下的视屏资源

Android 应用资源

如何从 Android 应用程序将 json 文件格式导入 CouchBase lite