This commit is contained in:
InsanusMokrassar 2019-03-21 12:25:23 +08:00
parent cbb3f2cc39
commit a18aed6c54
7 changed files with 213 additions and 15 deletions

View File

@ -1,8 +1,8 @@
kotlin.code.style=official kotlin.code.style=official
kotlin_version=1.3.11 kotlin_version=1.3.21
kotlin_coroutines_version=1.1.0 kotlin_coroutines_version=1.1.1
kotlin_serialisation_runtime_version=0.9.1 kotlin_serialisation_runtime_version=0.10.0
joda_time_version=2.10.1 joda_time_version=2.10.1
ktor_version=1.1.1 ktor_version=1.1.2
gradle_bintray_plugin_version=1.8.4 gradle_bintray_plugin_version=1.8.4

View File

@ -1,5 +1,6 @@
package com.github.insanusmokrassar.SauceNaoAPI package com.github.insanusmokrassar.SauceNaoAPI
import com.github.insanusmokrassar.SauceNaoAPI.models.Result
import com.github.insanusmokrassar.SauceNaoAPI.models.SauceNaoAnswer import com.github.insanusmokrassar.SauceNaoAPI.models.SauceNaoAnswer
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.call.call import io.ktor.client.call.call
@ -7,7 +8,7 @@ import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.request.parameter import io.ktor.client.request.parameter
import io.ktor.client.request.url import io.ktor.client.request.url
import io.ktor.client.response.readText import io.ktor.client.response.readText
import kotlinx.serialization.json.JSON import kotlinx.serialization.json.Json
private const val API_TOKEN_FIELD = "api_key" private const val API_TOKEN_FIELD = "api_key"
private const val OUTPUT_TYPE_FIELD = "output_type" private const val OUTPUT_TYPE_FIELD = "output_type"
@ -91,7 +92,7 @@ data class SauceNaoAPI(
resultsCount ?.also { parameter(RESULTS_COUNT_FIELD, it) } resultsCount ?.also { parameter(RESULTS_COUNT_FIELD, it) }
minSimilarity ?.also { parameter(MINIMAL_SIMILARITY_FIELD, it) } minSimilarity ?.also { parameter(MINIMAL_SIMILARITY_FIELD, it) }
}.response.readText().let { }.response.readText().let {
JSON.nonstrict.parse( Json.nonstrict.parse(
SauceNaoAnswer.serializer(), SauceNaoAnswer.serializer(),
it it
) )

View File

@ -1,7 +1,9 @@
package com.github.insanusmokrassar.SauceNaoAPI.models package com.github.insanusmokrassar.SauceNaoAPI.models
import kotlinx.serialization.SerialName import com.github.insanusmokrassar.SauceNaoAPI.utils.JsonObjectSerializer
import kotlinx.serialization.Serializable import kotlinx.serialization.*
import kotlinx.serialization.internal.*
import kotlinx.serialization.json.*
@Serializable @Serializable
data class Header( data class Header(
@ -21,8 +23,9 @@ data class Header(
val status: Int, val status: Int,
@SerialName("results_requested") @SerialName("results_requested")
val resultsRequested: Int, val resultsRequested: Int,
@Serializable(IndexesSerializer::class)
@SerialName("index") @SerialName("index")
val indexes: List<Index>, val indexes: List<HeaderIndex?>,
@SerialName("search_depth") @SerialName("search_depth")
val searchDepth: Int, val searchDepth: Int,
@SerialName("minimum_similarity") @SerialName("minimum_similarity")
@ -34,3 +37,23 @@ data class Header(
@SerialName("results_returned") @SerialName("results_returned")
val resultsCount: Int val resultsCount: Int
) )
object IndexesSerializer : KSerializer<List<HeaderIndex?>> {
override val descriptor: SerialDescriptor = StringDescriptor
override fun deserialize(decoder: Decoder): List<HeaderIndex?> {
val json = decoder.decodeSerializableValue(JsonObjectSerializer)
val parsed = json.keys.mapNotNull { it.toIntOrNull() }.sorted().mapNotNull {
val jsonObject = json.getObjectOrNull(it.toString()) ?: return@mapNotNull null
val index = Json.nonstrict.parse(HeaderIndex.serializer(), Json.stringify(JsonObjectSerializer, jsonObject))
it to index
}.toMap()
return Array<HeaderIndex?>(parsed.keys.max() ?: 0) {
parsed[it]
}.toList()
}
override fun serialize(encoder: Encoder, obj: List<HeaderIndex?>) {
TODO()
}
}

View File

@ -0,0 +1,14 @@
package com.github.insanusmokrassar.SauceNaoAPI.models
import kotlinx.serialization.Optional
import kotlinx.serialization.Serializable
@Serializable
data class HeaderIndex(
val status: Int,
val id: Int,
@Optional
val results: Int = 0,
@Optional
val parent_id: Int? = null
)

View File

@ -3,9 +3,7 @@ package com.github.insanusmokrassar.SauceNaoAPI.models
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
data class Index( data class Result(
val status: Int, val header: ResultHeader,
val parent_id: Int, val data: ResultData
val id: Int,
val results: Int
) )

View File

@ -5,5 +5,5 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
data class SauceNaoAnswer( data class SauceNaoAnswer(
val header: Header, val header: Header,
val data: ResultData val results: List<Result>
) )

View File

@ -0,0 +1,162 @@
package com.github.insanusmokrassar.SauceNaoAPI.utils
import kotlinx.serialization.*
import kotlinx.serialization.internal.*
import kotlinx.serialization.json.*
@Serializer(forClass = JsonElement::class)
internal object JsonElementSerializer : KSerializer<JsonElement> {
override val descriptor: SerialDescriptor = object : SerialClassDescImpl("JsonElementSerializer") {
override val kind: SerialKind
get() = UnionKind.SEALED
init {
addElement("JsonElement")
}
}
override fun serialize(encoder: Encoder, obj: JsonElement) {
when (obj) {
is JsonPrimitive -> JsonPrimitiveSerializer.serialize(encoder, obj)
is JsonObject -> JsonObjectSerializer.serialize(encoder, obj)
is JsonArray -> JsonArraySerializer.serialize(encoder, obj)
}
}
override fun deserialize(decoder: Decoder): JsonElement {
val input = decoder as? JsonInput ?: error("JsonElement is deserializable only when used by Json")
return input.decodeJson()
}
}
@Serializer(forClass = JsonPrimitive::class)
internal object JsonPrimitiveSerializer : KSerializer<JsonPrimitive> {
override val descriptor: SerialDescriptor =
JsonPrimitiveDescriptor
override fun serialize(encoder: Encoder, obj: JsonPrimitive) {
return if (obj is JsonNull) {
JsonNullSerializer.serialize(encoder, JsonNull)
} else {
JsonLiteralSerializer.serialize(encoder, obj as JsonLiteral)
}
}
override fun deserialize(decoder: Decoder): JsonPrimitive {
return if (decoder.decodeNotNullMark()) JsonPrimitive(decoder.decodeString())
else JsonNullSerializer.deserialize(decoder)
}
private object JsonPrimitiveDescriptor : SerialClassDescImpl("JsonPrimitive") {
override val kind: SerialKind
get() = PrimitiveKind.STRING
override val isNullable: Boolean
get() = true
init {
JsonPrimitiveSerializer.JsonPrimitiveDescriptor.addElement("JsonPrimitive")
}
}
}
@Serializer(forClass = JsonNull::class)
internal object JsonNullSerializer : KSerializer<JsonNull> {
override val descriptor: SerialDescriptor =
JsonNullDescriptor
override fun serialize(encoder: Encoder, obj: JsonNull) {
encoder.encodeNull()
}
override fun deserialize(decoder: Decoder): JsonNull {
decoder.decodeNull()
return JsonNull
}
private object JsonNullDescriptor : SerialClassDescImpl("JsonNull") {
override val kind: SerialKind
get() = UnionKind.OBJECT
override val isNullable: Boolean
get() = true
init {
JsonNullSerializer.JsonNullDescriptor.addElement("JsonNull")
}
}
}
@Serializer(forClass = JsonLiteral::class)
internal object JsonLiteralSerializer : KSerializer<JsonLiteral> {
override val descriptor: SerialDescriptor =
JsonLiteralDescriptor
override fun serialize(encoder: Encoder, obj: JsonLiteral) {
if (obj.isString) {
return encoder.encodeString(obj.content)
}
val integer = obj.intOrNull
if (integer != null) {
return encoder.encodeInt(integer)
}
val double = obj.doubleOrNull
if (double != null) {
return encoder.encodeDouble(double)
}
val boolean = obj.booleanOrNull
if (boolean != null) {
return encoder.encodeBoolean(boolean)
}
encoder.encodeString(obj.content)
}
override fun deserialize(decoder: Decoder): JsonLiteral {
return JsonLiteral(decoder.decodeString())
}
private object JsonLiteralDescriptor : SerialClassDescImpl("JsonLiteral") {
override val kind: SerialKind
get() = PrimitiveKind.STRING
init {
JsonLiteralSerializer.JsonLiteralDescriptor.addElement("JsonLiteral")
}
}
}
@Serializer(forClass = JsonObject::class)
internal object JsonObjectSerializer : KSerializer<JsonObject> {
override val descriptor: SerialDescriptor =
NamedMapClassDescriptor("JsonObject", StringSerializer.descriptor,
JsonElementSerializer.descriptor)
override fun serialize(encoder: Encoder, obj: JsonObject) {
LinkedHashMapSerializer(StringSerializer, JsonElementSerializer).serialize(encoder, obj.content)
}
override fun deserialize(decoder: Decoder): JsonObject {
return JsonObject(LinkedHashMapSerializer(StringSerializer, JsonElementSerializer).deserialize(decoder))
}
}
@Serializer(forClass = JsonArray::class)
internal object JsonArraySerializer : KSerializer<JsonArray> {
override val descriptor: SerialDescriptor = NamedListClassDescriptor("JsonArray",
JsonElementSerializer.descriptor)
override fun serialize(encoder: Encoder, obj: JsonArray) {
ArrayListSerializer(JsonElementSerializer).serialize(encoder, obj)
}
override fun deserialize(decoder: Decoder): JsonArray {
return JsonArray(ArrayListSerializer(JsonElementSerializer).deserialize(decoder))
}
}