Reputation: 21
I'm working in a Kotlin Multiplatform Library to share some logic for my native Android and iOS applications. I need to load a json file inside the commonMain directory, but I didn't find any documentation about that. I read about mocko-resources, but this dependency doesn't work for multiplatform libraries. I think this project is a multiplatform app project.
Project structure
https://i.sstatic.net/CFwu7.png
iOS Code
https://i.sstatic.net/yjogo.png
Android Code
https://i.sstatic.net/dzXgw.png
My idea is to open the local JSON and map the data into a Kotlin object. This is my project structure.
Upvotes: 2
Views: 1228
Reputation: 5025
For those looking for the answer in 2024 or later, there is an official Jetbrains library and Gradle plugin now!
https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-multiplatform-resources.html
You just need to:
compose.components.resources
dependency (coming from the org.jetbrains.compose
plugin)kotlin {
sourceSets {
commonMain.dependencies {
implementation(compose.components.resources)
}
}
}
Put your JSON files in composeApp/src/commonMain/composeResources/files
.
This particular path and files
folder is already preconfigured for you by the plugin.
If you want a custom directory structure, it's possible but you have to declare your resource path manually.
Read your JSON file using the autogenerated Res
class.
The path root is in composeResources
@OptIn(ExperimentalResourceApi::class)
suspend fun loadData(): List<Data> {
val readBytes = Res.readBytes("files/data.json")
val jsonString = String(readBytes)
return Json.decodeFromString(jsonString)
}
Upvotes: 1
Reputation: 61
Use expect and actual declarations to read the file on each platform, then you can convertit from json to kotlin object directly with the help of kotlinx.serialization library in commonMain.
code like:
val json = Json { ignoreUnknownKeys = true }
json.decodeFromString<Your Data Class>(your json content)
Upvotes: 1
Reputation: 6648
You need to implement file operations separately on each platform.
The most straightforward way is to use expect
and actual
declarations.
With this, you write an 'interface' for your function in commonMain
// commonMain/GetJson.kt
expect fun getJsonFromFile(file: String): String
Then add implementations for each platform:
// androidMain/GetJsonAndroid.kt
actual fun getJsonFromFile(file: String): String {
// Write code to read file using Android API
}
// iosMain/GetJsonIos.kt
actual fun getJsonFromFile(file: String): String {
// Write code to read file using iOS API
}
You can then call your function from commonMain
and complete your object creation using shared code.
// commonMain
class TargetObject(json: String) {
// implement in common code
}
val targetObject = TargetObject(getJsonFromFile())
Upvotes: 1