การใช้ไฟล์ JSON ในทรัพยากรแอป Android


88

สมมติว่าฉันมีไฟล์ที่มีเนื้อหา JSON อยู่ในโฟลเดอร์ทรัพยากรดิบในแอปของฉัน ฉันจะอ่านสิ่งนี้ในแอปได้อย่างไรจึงจะสามารถแยกวิเคราะห์ JSON ได้

คำตอบ:


145

ดู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
จะเกิดอะไรขึ้นถ้าฉันต้องการวางสตริงในทรัพยากร String ใน Android และใช้แบบไดนามิกโดยใช้ getResources () getString (R.String.name)
Ankur Gautam

สำหรับฉันมันไม่ได้ผลเพราะคำพูดซึ่งถูกละเลยเมื่ออ่านและดูเหมือนว่าจะไม่สามารถหลีกหนีได้
Marian Klühspies

1
มีวิธีใดบ้างที่จะทำให้ButterKnifeผูกทรัพยากรดิบได้? การเขียนโค้ดมากกว่า 10 บรรทัดเพื่ออ่านสตริงดูเหมือนจะเกินความจำเป็นเล็กน้อย
Jezor

json ถูกเก็บไว้ในทรัพยากรอย่างไร อยู่ใน\res\json_file.jsonโฟลเดอร์หรือภายใน\res\raw\json_file.json?
Cliff Burton

1
คำตอบนี้ไม่มีข้อมูลที่สำคัญ getResources()เรียกได้ว่าอยู่ที่ไหน? ไฟล์ทรัพยากรดิบควรอยู่ที่ไหน สิ่งที่การประชุมคุณควรปฏิบัติตามเพื่อให้แน่ใจว่าการสร้างเครื่องมือในการสร้างR.raw.json_file?
NobodyMan

114

ตอนนี้ Kotlin เป็นภาษาทางการสำหรับ Android ดังนั้นฉันคิดว่านี่น่าจะเป็นประโยชน์สำหรับใครบางคน

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

นี่เป็นการดำเนินการที่อาจใช้เวลานานดังนั้นตรวจสอบให้แน่ใจว่าสิ่งนี้ถูกเรียกออกจากเธรดหลัก!
Andrew Orobator

1
@AndrewOrobator ฉันสงสัยว่าจะมีคนใส่ json ขนาดใหญ่ไว้ในทรัพยากรของแอป แต่ใช่จุดที่ดี
Dima Rostopira

24

ฉันใช้คำตอบของ @ 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);
   }

3
อย่าลืมเพิ่มการอ้างอิง {compile com.google.code.gson: gson: 2.8.2 '} ลงในไฟล์ gradle ของคุณ
patrics

GSON เวอร์ชันสุดท้ายคือimplementation 'com.google.code.gson:gson:2.8.5'
Daniel

13

จากhttp://developer.android.com/guide/topics/resources/providing-resources.html :


ไฟล์ดิบ /ตามอำเภอใจเพื่อบันทึกในรูปแบบดิบ หากต้องการเปิดทรัพยากรเหล่านี้ด้วย InputStream แบบดิบให้เรียก Resources.openRawResource () ด้วยรหัสทรัพยากรซึ่งก็คือ R.raw.filename

อย่างไรก็ตามหากคุณต้องการเข้าถึงชื่อไฟล์ต้นฉบับและลำดับชั้นของไฟล์คุณอาจพิจารณาบันทึกทรัพยากรบางอย่างในเนื้อหา / ไดเร็กทอรี (แทน res / raw /) ไฟล์ในเนื้อหา / ไม่ได้รับ ID ทรัพยากรดังนั้นคุณสามารถอ่านได้โดยใช้ AssetManager เท่านั้น


5
หากฉันต้องการฝังไฟล์ JSON ในแอปของฉันฉันควรวางไว้ที่ไหน ในโฟลเดอร์สินทรัพย์หรือโฟลเดอร์ดิบ ขอบคุณ!
Ricardo

13

เช่นเดียวกับสถานะ @mah เอกสาร Android ( https://developer.android.com/guide/topics/resources/providing-resources.html ) บอกว่าไฟล์ json อาจถูกบันทึกในไดเร็กทอรี / raw ภายใต้ / res (ทรัพยากร) ไดเรกทอรีในโครงการของคุณตัวอย่างเช่น:

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

ภายในActivityไฟล์ json สามารถเข้าถึงได้ผ่านRคลาส (Resources) และอ่านเป็นสตริง:

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 ที่เป็นผลลัพธ์:

  • ใช้ Java / Android ที่สร้างขึ้นในJSONObjectและJSONArrayวัตถุเช่นที่นี่: JSON อาร์เรย์ย้ำใน Android มันอาจจะเป็นความสะดวกสบายที่จะได้รับสตริงจำนวนเต็ม ฯลฯ ใช้optString(String name), optInt(String name)วิธีการอื่น ๆ ไม่ได้getString(String name), getInt(String name)วิธีการเพราะoptวิธีการกลับ null แทนที่จะเป็นข้อยกเว้นในกรณีของความล้มเหลว
  • ใช้ไลบรารีอนุกรม / deserializing Java / Android json เหมือนที่ระบุไว้ที่นี่: https://medium.com/@IlyaEremin/android-json-parsers-comparison-2017-8b5221721e31

1
นี่ควรเป็นคำตอบที่ยอมรับเพียงสองบรรทัดและเสร็จสิ้นขอบคุณ
อาชนา Jackol

ความต้องการ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

พบว่าตัวอย่างข้อมูล Kotlin นี้มีประโยชน์มาก ♥️

ในขณะที่คำถามเดิมขอให้รับ JSON String แต่ฉันคิดว่าบางคนอาจพบว่ามีประโยชน์ ก้าวไปอีกขั้นด้วยGsonโอกาสในการขายไปยังฟังก์ชันเล็ก ๆ นี้ด้วยประเภท reified:

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<YourType>คุณจะไม่สูญเสียประเภทตามประเภทการลบ

ด้วยการอนุมานประเภทคุณสามารถใช้ดังนี้:

fun pricingData(): List<PricingData> = readRawJson(R.raw.mock_pricing_data)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.