From 251bf3d9df7ff5a26001df7224519b5fc8cfbcb3 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Mon, 5 Jul 2021 14:26:47 +0800
Subject: [PATCH] Add `JsonStruct` to simplify deserialization

---
 .../src/commonMain/kotlin/JsonStruct.kt       | 43 +++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 mirai-core-utils/src/commonMain/kotlin/JsonStruct.kt

diff --git a/mirai-core-utils/src/commonMain/kotlin/JsonStruct.kt b/mirai-core-utils/src/commonMain/kotlin/JsonStruct.kt
new file mode 100644
index 000000000..0ef4d9122
--- /dev/null
+++ b/mirai-core-utils/src/commonMain/kotlin/JsonStruct.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2021 Mamoe Technologies and contributors.
+ *
+ * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
+ * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
+ *
+ * https://github.com/mamoe/mirai/blob/dev/LICENSE
+ */
+
+package net.mamoe.mirai.utils
+
+import kotlinx.serialization.DeserializationStrategy
+import kotlinx.serialization.SerializationStrategy
+import kotlinx.serialization.json.Json
+import kotlin.reflect.typeOf
+
+public interface JsonStruct
+
+@PublishedApi
+internal val defaultJson: Json = Json {
+    isLenient = true
+    ignoreUnknownKeys = true
+}
+
+public fun <T : JsonStruct> String.loadAs(deserializer: DeserializationStrategy<T>, json: Json = defaultJson): T {
+    return json.decodeFromString(deserializer, this)
+}
+
+@OptIn(ExperimentalStdlibApi::class)
+public inline fun <reified T> String.loadSafelyAs(
+    deserializer: DeserializationStrategy<T>,
+    json: Json = defaultJson
+): Either<DeserializationFailure, T> where T : JsonStruct {
+    return try {
+        Either<DeserializationFailure, T>(json.decodeFromString(deserializer, this))
+    } catch (e: Throwable) {
+        // typeOf is used in ktor and coroutines so Kotlin will absolutely provide ABI guarantee for it.
+        Either(DeserializationFailure(typeOf<T>(), this, e))
+    }
+}
+
+public fun <T : JsonStruct> T.toJsonString(serializer: SerializationStrategy<T>, json: Json = defaultJson): String =
+    json.encodeToString(serializer, this)
\ No newline at end of file