Migrated to KotlinX Serialization library for JSON parsing
This commit is contained in:
1 parent
99158e74fa
commit
fb2cd85b11
9 files changed
+56
-57
No files matched your search
+1
-1
@@ -33,7 +33,7 @@ internal class CoreDataPlugin : Plugin<Project> {
|
|||||||
implementation(libs.androidx.room)
|
implementation(libs.androidx.room)
|
||||||
implementation(libs.androidx.room.runtime)
|
implementation(libs.androidx.room.runtime)
|
||||||
ksp(libs.androidx.room.compiler)
|
ksp(libs.androidx.room.compiler)
|
||||||
implementation(libs.other.coroutines)
|
implementation(libs.kotlin.coroutines)
|
||||||
implementation(libs.other.okhttp)
|
implementation(libs.other.okhttp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -25,10 +25,11 @@ import org.gradle.kotlin.dsl.dependencies
|
|||||||
internal class CoreDomainPlugin : Plugin<Project> {
|
internal class CoreDomainPlugin : Plugin<Project> {
|
||||||
override fun apply(target: Project) = with(target) {
|
override fun apply(target: Project) = with(target) {
|
||||||
applyPlugin(libs.plugins.kotlin.jvm)
|
applyPlugin(libs.plugins.kotlin.jvm)
|
||||||
|
applyPlugin(libs.plugins.kotlin.serialization)
|
||||||
setupKotlin()
|
setupKotlin()
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(libs.other.coroutines)
|
implementation(libs.kotlin.coroutines)
|
||||||
implementation(libs.other.json)
|
implementation(libs.kotlin.serialization)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ plugins {
|
|||||||
alias(libs.plugins.compose.compiler) apply false
|
alias(libs.plugins.compose.compiler) apply false
|
||||||
alias(libs.plugins.google.ksp) apply false
|
alias(libs.plugins.google.ksp) apply false
|
||||||
alias(libs.plugins.kotlin.jvm) apply false
|
alias(libs.plugins.kotlin.jvm) apply false
|
||||||
|
alias(libs.plugins.kotlin.serialization) apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("clean", Delete::class.java) {
|
tasks.register("clean", Delete::class.java) {
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ data class SatRadio(
|
|||||||
@PrimaryKey val uuid: String,
|
@PrimaryKey val uuid: String,
|
||||||
val info: String,
|
val info: String,
|
||||||
val isAlive: Boolean,
|
val isAlive: Boolean,
|
||||||
var downlinkLow: Long?,
|
val downlinkLow: Long?,
|
||||||
var downlinkHigh: Long?,
|
val downlinkHigh: Long?,
|
||||||
val downlinkMode: String?,
|
val downlinkMode: String?,
|
||||||
var uplinkLow: Long?,
|
val uplinkLow: Long?,
|
||||||
var uplinkHigh: Long?,
|
val uplinkHigh: Long?,
|
||||||
val uplinkMode: String?,
|
val uplinkMode: String?,
|
||||||
val isInverted: Boolean,
|
val isInverted: Boolean,
|
||||||
val catnum: Int?
|
val catnum: Int?
|
||||||
|
|||||||
@@ -17,16 +17,20 @@
|
|||||||
*/
|
*/
|
||||||
package com.rtbishop.look4sat.core.domain.model
|
package com.rtbishop.look4sat.core.domain.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class SatRadio(
|
data class SatRadio(
|
||||||
val uuid: String,
|
@SerialName("uuid") val uuid: String,
|
||||||
val info: String,
|
@SerialName("description") val info: String,
|
||||||
val isAlive: Boolean,
|
@SerialName("alive") val isAlive: Boolean,
|
||||||
var downlinkLow: Long?,
|
@SerialName("downlink_low") val downlinkLow: Long?,
|
||||||
var downlinkHigh: Long?,
|
@SerialName("downlink_high") val downlinkHigh: Long?,
|
||||||
val downlinkMode: String?,
|
@SerialName("mode") val downlinkMode: String?,
|
||||||
var uplinkLow: Long?,
|
@SerialName("uplink_low") val uplinkLow: Long?,
|
||||||
var uplinkHigh: Long?,
|
@SerialName("uplink_high") val uplinkHigh: Long?,
|
||||||
val uplinkMode: String?,
|
@SerialName("uplink_mode") val uplinkMode: String?,
|
||||||
val isInverted: Boolean,
|
@SerialName("invert") val isInverted: Boolean,
|
||||||
val catnum: Int?
|
@SerialName("norad_cat_id") val catnum: Int?
|
||||||
)
|
)
|
||||||
@@ -21,13 +21,19 @@ import com.rtbishop.look4sat.core.domain.model.SatRadio
|
|||||||
import com.rtbishop.look4sat.core.domain.predict.OrbitalData
|
import com.rtbishop.look4sat.core.domain.predict.OrbitalData
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.json.JSONArray
|
import kotlinx.serialization.json.Json
|
||||||
import org.json.JSONObject
|
import kotlinx.serialization.json.JsonArray
|
||||||
|
import kotlinx.serialization.json.decodeFromJsonElement
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
class DataParser(private val dispatcher: CoroutineDispatcher) {
|
class DataParser(private val dispatcher: CoroutineDispatcher) {
|
||||||
|
|
||||||
|
private val json = Json {
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
coerceInputValues = true
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun parseCSVStream(stream: InputStream): List<OrbitalData> = withContext(dispatcher) {
|
suspend fun parseCSVStream(stream: InputStream): List<OrbitalData> = withContext(dispatcher) {
|
||||||
stream.bufferedReader().useLines { lines ->
|
stream.bufferedReader().useLines { lines ->
|
||||||
lines.drop(1).mapNotNull { parseCSV(it.split(",")) }.toList()
|
lines.drop(1).mapNotNull { parseCSV(it.split(",")) }.toList()
|
||||||
@@ -43,8 +49,12 @@ class DataParser(private val dispatcher: CoroutineDispatcher) {
|
|||||||
|
|
||||||
suspend fun parseJSONStream(stream: InputStream): List<SatRadio> = withContext(dispatcher) {
|
suspend fun parseJSONStream(stream: InputStream): List<SatRadio> = withContext(dispatcher) {
|
||||||
runCatching {
|
runCatching {
|
||||||
val jsonArray = JSONArray(stream.bufferedReader().readText())
|
val root = json.parseToJsonElement(stream.bufferedReader().readText())
|
||||||
(0 until jsonArray.length()).mapNotNull { parseJSON(jsonArray.getJSONObject(it)) }
|
(root as? JsonArray)?.mapNotNull { element ->
|
||||||
|
runCatching { json.decodeFromJsonElement<SatRadio>(element) }
|
||||||
|
.onFailure { println("JSON parsing exception: $it") }
|
||||||
|
.getOrNull()
|
||||||
|
} ?: emptyList()
|
||||||
}.getOrDefault(emptyList())
|
}.getOrDefault(emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,26 +105,6 @@ class DataParser(private val dispatcher: CoroutineDispatcher) {
|
|||||||
)
|
)
|
||||||
}.onFailure { println("TLE parsing exception: $it") }.getOrNull()
|
}.onFailure { println("TLE parsing exception: $it") }.getOrNull()
|
||||||
|
|
||||||
private fun parseJSON(json: JSONObject): SatRadio? = runCatching {
|
|
||||||
SatRadio(
|
|
||||||
uuid = json.getString("uuid"),
|
|
||||||
info = json.getString("description"),
|
|
||||||
isAlive = json.getBoolean("alive"),
|
|
||||||
downlinkLow = json.optLongOrNull("downlink_low"),
|
|
||||||
downlinkHigh = json.optLongOrNull("downlink_high"),
|
|
||||||
downlinkMode = json.optStringOrNull("mode"),
|
|
||||||
uplinkLow = json.optLongOrNull("uplink_low"),
|
|
||||||
uplinkHigh = json.optLongOrNull("uplink_high"),
|
|
||||||
uplinkMode = json.optStringOrNull("uplink_mode"),
|
|
||||||
isInverted = json.getBoolean("invert"),
|
|
||||||
catnum = json.optIntOrNull("norad_cat_id")
|
|
||||||
)
|
|
||||||
}.onFailure { println("JSON parsing exception: $it") }.getOrNull()
|
|
||||||
|
|
||||||
private fun JSONObject.optStringOrNull(key: String): String? = if (isNull(key)) null else getString(key)
|
|
||||||
private fun JSONObject.optLongOrNull(key: String): Long? = if (isNull(key)) null else getLong(key)
|
|
||||||
private fun JSONObject.optIntOrNull(key: String): Int? = if (isNull(key)) null else getInt(key)
|
|
||||||
|
|
||||||
private fun getDayOfYear(year: Int, month: Int, dayOfMonth: Int): Int {
|
private fun getDayOfYear(year: Int, month: Int, dayOfMonth: Int): Int {
|
||||||
val daysInMonth = intArrayOf(31, if (isLeapYear(year)) 29 else 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
val daysInMonth = intArrayOf(31, if (isLeapYear(year)) 29 else 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||||
return daysInMonth.take(month - 1).sum() + dayOfMonth
|
return daysInMonth.take(month - 1).sum() + dayOfMonth
|
||||||
|
|||||||
+2
-2
@@ -2,9 +2,9 @@ package com.rtbishop.look4sat.core.domain
|
|||||||
|
|
||||||
import com.rtbishop.look4sat.core.domain.model.SatRadio
|
import com.rtbishop.look4sat.core.domain.model.SatRadio
|
||||||
import com.rtbishop.look4sat.core.domain.utility.TransponderMapper
|
import com.rtbishop.look4sat.core.domain.utility.TransponderMapper
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertNull
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertEquals
|
|
||||||
import kotlin.test.assertNull
|
|
||||||
|
|
||||||
class TransponderMapperTest {
|
class TransponderMapperTest {
|
||||||
|
|
||||||
|
|||||||
@@ -149,8 +149,8 @@ private fun RadarScreen(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun RadarCard(uiState: RadarState, modifier: Modifier = Modifier) {
|
private fun RadarCard(uiState: RadarState, modifier: Modifier = Modifier) {
|
||||||
val isEclipsed = uiState.orbitalPos?.eclipsed == true
|
val satellitePos = uiState.orbitalPos
|
||||||
val borderModifier = if (isEclipsed) {
|
val borderModifier = if (satellitePos?.aboveHorizon == true && satellitePos.eclipsed) {
|
||||||
val infiniteTransition = rememberInfiniteTransition(label = "eclipsedBorder")
|
val infiniteTransition = rememberInfiniteTransition(label = "eclipsedBorder")
|
||||||
val borderAlpha by infiniteTransition.animateFloat(
|
val borderAlpha by infiniteTransition.animateFloat(
|
||||||
initialValue = 1.0f,
|
initialValue = 1.0f,
|
||||||
|
|||||||
+14
-11
@@ -12,9 +12,7 @@ jdkVersion = "17"
|
|||||||
#noinspection UnusedVersionCatalogEntry
|
#noinspection UnusedVersionCatalogEntry
|
||||||
packageName = "com.rtbishop.look4sat"
|
packageName = "com.rtbishop.look4sat"
|
||||||
|
|
||||||
android-gradle-plugin = "9.1.1"
|
android-gradle-plugin = "9.2.0"
|
||||||
google-ksp = "2.3.6"
|
|
||||||
kotlin = "2.3.20"
|
|
||||||
|
|
||||||
androidx-core-ktx = "1.18.0"
|
androidx-core-ktx = "1.18.0"
|
||||||
androidx-core-splashscreen = "1.2.0"
|
androidx-core-splashscreen = "1.2.0"
|
||||||
@@ -25,8 +23,12 @@ compose-activity = "1.13.0"
|
|||||||
compose-lifecycle = "2.10.0"
|
compose-lifecycle = "2.10.0"
|
||||||
compose-navigation = "2.9.7"
|
compose-navigation = "2.9.7"
|
||||||
|
|
||||||
other-coroutines = "1.10.2"
|
google-ksp = "2.3.6"
|
||||||
other-json = "20251224"
|
|
||||||
|
kotlin = "2.3.20"
|
||||||
|
kotlin-coroutines = "1.10.2"
|
||||||
|
kotlin-serialization = "1.11.0"
|
||||||
|
|
||||||
other-okhttp = "5.3.2"
|
other-okhttp = "5.3.2"
|
||||||
other-osmdroid = "6.1.20"
|
other-osmdroid = "6.1.20"
|
||||||
|
|
||||||
@@ -64,18 +66,18 @@ compose-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel-compose",
|
|||||||
compose-debug-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
compose-debug-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
||||||
compose-debug-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
compose-debug-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
||||||
|
|
||||||
kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
|
#noinspection UnusedVersionCatalogEntry
|
||||||
|
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
|
||||||
|
kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||||
|
#noinspection UnusedVersionCatalogEntry
|
||||||
|
kotlin-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlin-serialization" }
|
||||||
|
|
||||||
#noinspection UnusedVersionCatalogEntry
|
|
||||||
other-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "other-coroutines" }
|
|
||||||
#noinspection UnusedVersionCatalogEntry
|
|
||||||
other-json = { module = "org.json:json", version.ref = "other-json" }
|
|
||||||
#noinspection UnusedVersionCatalogEntry
|
#noinspection UnusedVersionCatalogEntry
|
||||||
other-okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "other-okhttp" }
|
other-okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "other-okhttp" }
|
||||||
#noinspection UnusedVersionCatalogEntry
|
#noinspection UnusedVersionCatalogEntry
|
||||||
other-osmdroid = { module = "org.osmdroid:osmdroid-android", version.ref = "other-osmdroid" }
|
other-osmdroid = { module = "org.osmdroid:osmdroid-android", version.ref = "other-osmdroid" }
|
||||||
|
|
||||||
test-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "other-coroutines" }
|
test-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlin-coroutines" }
|
||||||
test-junit4 = { module = "junit:junit", version.ref = "test-junit4" }
|
test-junit4 = { module = "junit:junit", version.ref = "test-junit4" }
|
||||||
|
|
||||||
androidTest-junit = { module = "androidx.test.ext:junit", version.ref = "androidTest-junit" }
|
androidTest-junit = { module = "androidx.test.ext:junit", version.ref = "androidTest-junit" }
|
||||||
@@ -87,6 +89,7 @@ android-library = { id = "com.android.library", version.ref = "android-gradle-pl
|
|||||||
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||||
google-ksp = { id = "com.google.devtools.ksp", version.ref = "google-ksp" }
|
google-ksp = { id = "com.google.devtools.ksp", version.ref = "google-ksp" }
|
||||||
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||||
|
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
||||||
# plugins defined by this project
|
# plugins defined by this project
|
||||||
convention-applicationPlugin = { id = "com.rtbishop.look4sat.convention.applicationPlugin" }
|
convention-applicationPlugin = { id = "com.rtbishop.look4sat.convention.applicationPlugin" }
|
||||||
convention-coreDataPlugin = { id = "com.rtbishop.look4sat.convention.coreDataPlugin" }
|
convention-coreDataPlugin = { id = "com.rtbishop.look4sat.convention.coreDataPlugin" }
|
||||||
|
|||||||
Reference in new issue
Block a user