-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJsonViewModelDecoder.kt
More file actions
102 lines (88 loc) · 3.96 KB
/
JsonViewModelDecoder.kt
File metadata and controls
102 lines (88 loc) · 3.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package com.dmm.eikaiwa.viewmodels
import com.dmm.eikaiwa.common.Logger
import com.dmm.eikaiwa.viewmodels.errors.ViewModelError
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.jsonObject
private val logger = Logger.get<JsonViewModelDecoder>()
class JsonViewModelDecoder(
val stringData: String,
val jsonParser: Json
) {
private val referenceCache: ViewModelReferenceCache
get() {
val contextSerializer = jsonParser.serializersModule.getContextual(
ViewModelContext::class
) as? ViewModelContextSerializer ?: throw ReferenceCacheNotFoundException()
return contextSerializer.referenceCache
}
fun <Model, Meta, Supplementary> parse(
modelSerializer: KSerializer<Model>,
metaSerializer: KSerializer<Meta>,
supplementarySerializer: KSerializer<Supplementary>
): ViewModelParseResult<Model, Meta, Supplementary> {
try {
val rootElement = jsonParser.parseToJsonElement(stringData)
// References: read and store them raw.
parseReferences(rootElement)
// Data.
val dataObject = rootElement.jsonObject["data"]!!
val model = jsonParser.decodeFromJsonElement(modelSerializer, dataObject)
// Meta.
val meta = parseMeta(rootElement, metaSerializer)
// Supplementary. Contained within meta.
val supplementary = parseSupplementary(rootElement, supplementarySerializer)
return ViewModelParseResult.Success(model, meta, supplementary)
} catch (e: Throwable) {
logger.error { "Error decoding JSON: $e" }
return ViewModelParseResult.Error(e)
}
}
private fun <Meta> parseMeta(rootElement: JsonElement, metaSerializer: KSerializer<Meta>): Meta {
val metaJsonObject = rootElement.jsonObject["meta"]
return metaJsonObject!!.let {
jsonParser.decodeFromJsonElement(metaSerializer, it)
}
}
private fun <Supplementary> parseSupplementary(rootElement: JsonElement, supplementarySerializer: KSerializer<Supplementary>): Supplementary =
(rootElement.jsonObject["meta"]?.jsonObject?.get("supplementary") ?: buildJsonObject { } ).let {
jsonParser.decodeFromJsonElement(supplementarySerializer, it)
}
fun <Model> parse(
modelSerializer: KSerializer<Model>
): ViewModelParseResult<Model, Unit, Unit> {
try {
val rootElement = jsonParser.parseToJsonElement(stringData)
// References: read and store them raw.
parseReferences(rootElement)
// Data.
val dataObject = rootElement.jsonObject["data"]!!
val model = jsonParser.decodeFromJsonElement(modelSerializer, dataObject)
return ViewModelParseResult.Success(model, Unit, Unit)
} catch (e: Throwable) {
logger.error { "Error decoding JSON: $e" }
return ViewModelParseResult.Error(e)
}
}
fun parseError(): ViewModelParseResult<ViewModelError, Unit, Unit> {
try {
val rootElement = jsonParser.parseToJsonElement(stringData)
// Error.
val dataObject = rootElement.jsonObject["error"]!!
val model = jsonParser.decodeFromJsonElement(ViewModelError.serializer(), dataObject)
return ViewModelParseResult.Success(model, Unit, Unit)
} catch (e: Throwable) {
logger.error { "Error decoding JSON: $e" }
return ViewModelParseResult.Error(e)
}
}
private fun parseReferences(rootElement: JsonElement) {
rootElement.jsonObject["references"]?.let { referencesElement ->
referenceCache.raw += referencesElement.jsonObject.entries.map { (key, value) ->
key to value.jsonObject
}
}
}
}