Moshi parsing with InputStream
Asked Answered
M

2

5

Assuming I need to parse a huge list of Items from a json asset file in Android with the format similar to below:

[
    {
        "id": 1,
        "name: "Tom"
        // other stuff to describe "Item"
    }
]

For performance reason I want to avoid converting the whole file into a single String and parse it using moshi. I want instead to use stream and parse each item from json to Item and construct the list of items myself. With gson I think it can be done like this:

Gson gson = new GsonBuilder().create();
List<Item> items = new ArrayList<>();

// Read file in stream mode
try (JsonReader reader = new JsonReader(in)) {
     reader.beginArray();
     while (reader.hasNext()) {
        // Read data into object model
        Item item = gson.fromJson(reader, Item.class);
        items.add(item);
     }
  } catch ...

}

I have been searching for a while but couldn't find Moshi's equivalent way for doing this. Any advice?

Thanks

Mechanics answered 14/2, 2020 at 13:21 Comment(0)
H
4

Okio.buffer(Okio.source(open(jsonFile))) got deprecated, now there are extensions for this.

val inputStream = appContext.resources.openRawResource(R.raw.blah)
val adapter: JsonAdapter<MyDataClass> = moshi.adapter()

adapter.fromJson(inputStream.source().buffer())
Harr answered 2/4, 2022 at 13:45 Comment(1)
Where did you see that Okio.buffer(Okio.source(open(jsonFile))) got deprecated? Does it say this in the docs? In fact where can you even find any useful API documentation on Okio 2.x?Drachma
S
2

Moshi uses Okio so you can do something like this for streaming json:

private val moshi by lazy {
    Moshi.Builder().build()
}

private val adapter by lazy {
    moshi.adapter(Layout::class.java)
}

fun AssetManager.layoutsFromJson(jsonFile: String): List<Layout> {
    val layouts = mutableListOf<Layout>()
    JsonReader.of(Okio.buffer(Okio.source(open(jsonFile)))).use { reader ->
        reader.beginArray()
        while (reader.hasNext()) {
            adapter.fromJson(reader)?.let {
                layouts.add(it)
            }
        }
    }
    return layouts
}

fun Fragment.layoutsAsset(jsonFile: String): List<Layout> {
    return context?.assets?.layoutsFromJson(jsonFile) ?: emptyList()
}
Sure answered 10/4, 2020 at 19:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.