Skip to content

Commit 8a48e42

Browse files
committed
feat(json): added orNull variants for serialization functions
Added safer `orNull` alternatives for various JSON serialization and deserialization methods to gracefully handle exceptions and invalid data. Updated deprecated methods to reference these new utilities.
1 parent 5732fa5 commit 8a48e42

2 files changed

Lines changed: 160 additions & 127 deletions

File tree

module-extkt-json/src/commonMain/kotlin/ExtensionSerialization.kt

Lines changed: 107 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -16,70 +16,93 @@
1616
package org.cufy.json
1717

1818
import kotlinx.serialization.SerializationException
19-
import kotlinx.serialization.encodeToString
2019
import kotlinx.serialization.json.*
21-
import kotlin.Result.Companion.failure
22-
import kotlin.Result.Companion.success
20+
21+
private const val DEP_MSG = "Serialization extensions for json util is confusing"
2322

2423
// JsonElement <= String
2524

26-
@Deprecated("Use the new name", ReplaceWith("decodeJson(json)"))
27-
fun String.decodeJsonString(json: Json = Json): JsonElement = decodeJson(json)
25+
@Deprecated(DEP_MSG, ReplaceWith("json.parseToJsonElement(this)"))
26+
fun String.decodeJsonString(json: Json = Json): JsonElement =
27+
json.parseToJsonElement(this)
2828

29-
@Deprecated("Use the new name", ReplaceWith("decodeJsonOrNull(json)"))
30-
fun String.decodeJsonStringOrNull(json: Json = Json): JsonElement? = decodeJsonOrNull(json)
29+
@Deprecated(DEP_MSG, ReplaceWith("json.parseToJsonElementOrNull(this)"))
30+
fun String.decodeJsonStringOrNull(json: Json = Json): JsonElement? =
31+
json.parseToJsonElementOrNull(this)
3132

3233
/**
3334
* Deserializes [this] JSON string into a corresponding [JsonElement] representation.
3435
*
3536
* @throws [SerializationException] if the given string is not a valid JSON
3637
*/
37-
fun String.decodeJson(json: Json = Json): JsonElement {
38-
return json.parseToJsonElement(this)
39-
}
38+
@Deprecated(DEP_MSG, ReplaceWith("json.parseToJsonElement(this)"))
39+
fun String.decodeJson(json: Json = Json): JsonElement =
40+
json.parseToJsonElement(this)
4041

4142
/**
4243
* Tries to deserialize [this] JSON string into a corresponding [JsonElement] representation.
4344
* Returns `null` when on failure.
4445
*/
45-
fun String.decodeJsonOrNull(json: Json = Json): JsonElement? {
46-
return try {
47-
json.parseToJsonElement(this)
48-
} catch (_: SerializationException) {
49-
return null
50-
}
51-
}
46+
@Deprecated(DEP_MSG, ReplaceWith("json.parseToJsonElementOrNull(this)"))
47+
fun String.decodeJsonOrNull(json: Json = Json): JsonElement? =
48+
json.parseToJsonElementOrNull(this)
5249

5350
/**
5451
* Tries to deserialize [this] JSON string into a corresponding [JsonElement] representation.
5552
*/
56-
fun String.decodeJsonCatching(json: Json = Json): Result<JsonElement> {
57-
return try {
58-
success(json.parseToJsonElement(this))
59-
} catch (e: SerializationException) {
60-
failure(e)
61-
}
62-
}
53+
@Deprecated(DEP_MSG, ReplaceWith("runCatching { json.parseToJsonElement(this) }"))
54+
fun String.decodeJsonCatching(json: Json = Json): Result<JsonElement> =
55+
runCatching { json.parseToJsonElement(this) }
56+
57+
// JsonObject <= String
58+
59+
/**
60+
* Deserializes [this] JSON string into a corresponding [JsonObject] representation.
61+
*
62+
* @throws [SerializationException] if the given string is not a valid JSON
63+
* @throws [ClassCastException] if the given value was not serialized to JsonObject.
64+
*/
65+
@Deprecated(DEP_MSG, ReplaceWith("json.parseToJsonElement(this).asJsonObject"))
66+
fun String.decodeJsonObject(json: Json = Json): JsonObject =
67+
json.parseToJsonElement(this).asJsonObject
68+
69+
/**
70+
* Tries to deserialize [this] JSON string into a corresponding [JsonObject] representation.
71+
* Returns `null` when on failure.
72+
*/
73+
@Deprecated(DEP_MSG, ReplaceWith("json.parseToJsonElementOrNull(this)?.asJsonObjectOrNull"))
74+
fun String.decodeJsonObjectOrNull(json: Json = Json): JsonObject? =
75+
json.parseToJsonElementOrNull(this)?.asJsonObjectOrNull
76+
77+
/**
78+
* Tries to deserialize [this] JSON string into a corresponding [JsonObject] representation.
79+
*/
80+
@Deprecated(DEP_MSG, ReplaceWith("runCatching { json.parseToJsonElement(this).asJsonObject }"))
81+
fun String.decodeJsonObjectCatching(json: Json = Json): Result<JsonObject> =
82+
runCatching { json.parseToJsonElement(this).asJsonObject }
6383

6484
// JsonElement => String
6585

66-
@Deprecated("Use the new name", ReplaceWith("encodeToString(json)"))
67-
fun JsonElement.encodeToJsonString(json: Json = Json): String = encodeToString(json)
86+
@Deprecated(DEP_MSG, ReplaceWith("json.encodeToString(this)"))
87+
fun JsonElement.encodeToJsonString(json: Json = Json): String =
88+
json.encodeToString(this)
6889

6990
/**
7091
* Serializes [this] [JsonElement] representation into JSON string.
7192
*/
72-
fun JsonElement.encodeToString(json: Json = Json): String {
73-
return json.encodeToString(this)
74-
}
93+
@Deprecated(DEP_MSG, ReplaceWith("json.encodeToString(this)"))
94+
fun JsonElement.encodeToString(json: Json = Json): String =
95+
json.encodeToString(this)
7596

7697
// T <= String
7798

78-
@Deprecated("Use the new name", ReplaceWith("deserializeJson<T>(json)"))
79-
inline fun <reified T> String.deserializeJsonString(json: Json = Json): T = deserializeJson(json)
99+
@Deprecated(DEP_MSG, ReplaceWith("json.decodeFromString<T>(this)"))
100+
inline fun <reified T> String.deserializeJsonString(json: Json = Json): T =
101+
json.decodeFromString<T>(this)
80102

81-
@Deprecated("Use the new name", ReplaceWith("deserializeJsonOrNull<T>(json)"))
82-
inline fun <reified T> String.deserializeJsonStringOrNull(json: Json = Json): T? = deserializeJsonOrNull(json)
103+
@Deprecated(DEP_MSG, ReplaceWith("json.decodeFromStringOrNull<T>(this)"))
104+
inline fun <reified T> String.deserializeJsonStringOrNull(json: Json = Json): T? =
105+
json.decodeFromStringOrNull<T>(this)
83106

84107
/**
85108
* Decodes and deserializes [this] string to the value of type [T] using deserializer
@@ -88,46 +111,36 @@ inline fun <reified T> String.deserializeJsonStringOrNull(json: Json = Json): T?
88111
* @throws SerializationException in case of any decoding-specific error
89112
* @throws IllegalArgumentException if the decoded input is not a valid instance of [T]
90113
*/
91-
inline fun <reified T> String.deserializeJson(json: Json = Json): T {
92-
return json.decodeFromString(this)
93-
}
114+
@Deprecated(DEP_MSG, ReplaceWith("json.decodeFromString<T>(this)"))
115+
inline fun <reified T> String.deserializeJson(json: Json = Json): T =
116+
json.decodeFromString<T>(this)
94117

95118
/**
96119
* Decodes and deserializes [this] string to the value of type [T] using deserializer
97120
* retrieved from the reified type parameter.
98121
* Returns `null` when on failure.
99122
*/
100-
inline fun <reified T> String.deserializeJsonOrNull(json: Json = Json): T? {
101-
return try {
102-
json.decodeFromString(this)
103-
} catch (_: SerializationException) {
104-
null
105-
} catch (_: IllegalArgumentException) {
106-
null
107-
}
108-
}
123+
@Deprecated(DEP_MSG, ReplaceWith("json.decodeFromStringOrNull<T>(this)"))
124+
inline fun <reified T> String.deserializeJsonOrNull(json: Json = Json): T? =
125+
json.decodeFromStringOrNull<T>(this)
109126

110127
/**
111128
* Decodes and deserializes [this] string to the value of type [T] using deserializer
112129
* retrieved from the reified type parameter.
113130
*/
114-
inline fun <reified T> String.deserializeJsonCatching(json: Json = Json): Result<T> {
115-
return try {
116-
success(json.decodeFromString<T>(this))
117-
} catch (e: SerializationException) {
118-
failure(e)
119-
} catch (e: IllegalArgumentException) {
120-
failure(e)
121-
}
122-
}
131+
@Deprecated(DEP_MSG, ReplaceWith("runCatching { json.decodeFromString<T>(this) }"))
132+
inline fun <reified T> String.deserializeJsonCatching(json: Json = Json): Result<T> =
133+
runCatching { json.decodeFromString<T>(this) }
123134

124135
// T <= JsonElement
125136

126-
@Deprecated("Use the new name", ReplaceWith("deserialize<T>(json)"))
127-
inline fun <reified T> JsonElement.deserializeJsonElement(json: Json = Json): T = deserialize(json)
137+
@Deprecated(DEP_MSG, ReplaceWith("json.decodeFromJsonElement<T>(this)"))
138+
inline fun <reified T> JsonElement.deserializeJsonElement(json: Json = Json): T =
139+
json.decodeFromJsonElement<T>(this)
128140

129-
@Deprecated("Use the new name", ReplaceWith("deserializeOrNull<T>(json)"))
130-
inline fun <reified T> JsonElement.deserializeJsonElementOrNull(json: Json = Json): T? = deserializeOrNull(json)
141+
@Deprecated("Use the new name", ReplaceWith("json.decodeFromJsonElementOrNull<T>(this)"))
142+
inline fun <reified T> JsonElement.deserializeJsonElementOrNull(json: Json = Json): T? =
143+
json.decodeFromJsonElementOrNull<T>(this)
131144

132145
/**
133146
* Deserializes [this] json element into a value of type [T] using a deserializer retrieved
@@ -136,38 +149,26 @@ inline fun <reified T> JsonElement.deserializeJsonElementOrNull(json: Json = Jso
136149
* @throws [SerializationException] if the given JSON element is not a valid JSON input for the type [T]
137150
* @throws [IllegalArgumentException] if the decoded input cannot be represented as a valid instance of type [T]
138151
*/
139-
inline fun <reified T> JsonElement.deserialize(json: Json = Json): T {
140-
return json.decodeFromJsonElement(this)
141-
}
152+
@Deprecated(DEP_MSG, ReplaceWith("json.decodeFromJsonElement<T>(this)"))
153+
inline fun <reified T> JsonElement.deserialize(json: Json = Json): T =
154+
json.decodeFromJsonElement<T>(this)
142155

143156
/**
144157
* Deserializes [this] json element into a value of type [T] using a deserializer retrieved
145158
* from reified type parameter.
146159
* Returns `null` when on failure.
147160
*/
148-
inline fun <reified T> JsonElement.deserializeOrNull(json: Json = Json): T? {
149-
return try {
150-
json.decodeFromJsonElement(this)
151-
} catch (_: SerializationException) {
152-
null
153-
} catch (_: IllegalArgumentException) {
154-
null
155-
}
156-
}
161+
@Deprecated(DEP_MSG, ReplaceWith("json.decodeFromJsonElementOrNull<T>(this)"))
162+
inline fun <reified T> JsonElement.deserializeOrNull(json: Json = Json): T? =
163+
json.decodeFromJsonElementOrNull<T>(this)
157164

158165
/**
159166
* Deserializes [this] json element into a value of type [T] using a deserializer retrieved
160167
* from reified type parameter.
161168
*/
162-
inline fun <reified T> JsonElement.deserializeCatching(json: Json = Json): Result<T> {
163-
return try {
164-
success(json.decodeFromJsonElement<T>(this))
165-
} catch (e: SerializationException) {
166-
failure(e)
167-
} catch (e: IllegalArgumentException) {
168-
failure(e)
169-
}
170-
}
169+
@Deprecated(DEP_MSG, ReplaceWith("runCatching { json.decodeFromJsonElement<T>(this) }"))
170+
inline fun <reified T> JsonElement.deserializeCatching(json: Json = Json): Result<T> =
171+
runCatching { json.decodeFromJsonElement<T>(this) }
171172

172173
// T => String
173174

@@ -177,36 +178,24 @@ inline fun <reified T> JsonElement.deserializeCatching(json: Json = Json): Resul
177178
* @throws SerializationException in case of any encoding-specific error
178179
* @throws IllegalArgumentException if the encoded input does not comply format's specification
179180
*/
180-
inline fun <reified T> T.serializeToJsonString(json: Json = Json): String {
181-
return json.encodeToString(this)
182-
}
181+
@Deprecated(DEP_MSG, ReplaceWith("json.encodeToString<T>(this)"))
182+
inline fun <reified T> T.serializeToJsonString(json: Json = Json): String =
183+
json.encodeToString<T>(this)
183184

184185
/**
185186
* Serializes and encodes [this] to string using serializer retrieved from the reified type parameter.
186187
* Returns `null` when on failure.
187188
*/
188-
inline fun <reified T> T.serializeToJsonStringOrNull(json: Json = Json): String? {
189-
return try {
190-
json.encodeToString(this)
191-
} catch (_: SerializationException) {
192-
null
193-
} catch (_: IllegalArgumentException) {
194-
null
195-
}
196-
}
189+
@Deprecated(DEP_MSG, ReplaceWith("json.encodeToStringOrNull<T>(this)"))
190+
inline fun <reified T> T.serializeToJsonStringOrNull(json: Json = Json): String? =
191+
json.encodeToStringOrNull<T>(this)
197192

198193
/**
199194
* Serializes and encodes [this] to string using serializer retrieved from the reified type parameter.
200195
*/
201-
inline fun <reified T> T.serializeToJsonStringCatching(json: Json = Json): Result<String> {
202-
return try {
203-
success(json.encodeToString(this))
204-
} catch (e: SerializationException) {
205-
failure(e)
206-
} catch (e: IllegalArgumentException) {
207-
failure(e)
208-
}
209-
}
196+
@Deprecated(DEP_MSG, ReplaceWith("runCatching { json.encodeToString<T>(this) }"))
197+
inline fun <reified T> T.serializeToJsonStringCatching(json: Json = Json): Result<String> =
198+
runCatching { json.encodeToString<T>(this) }
210199

211200
// T => JsonElement
212201

@@ -216,34 +205,26 @@ inline fun <reified T> T.serializeToJsonStringCatching(json: Json = Json): Resul
216205
*
217206
* @throws [SerializationException] if the given value cannot be serialized to JSON.
218207
*/
219-
inline fun <reified T> T.serializeToJsonElement(json: Json = Json): JsonElement {
220-
return json.encodeToJsonElement(this)
221-
}
208+
@Deprecated(DEP_MSG, ReplaceWith("json.encodeToJsonElement<T>(this)"))
209+
inline fun <reified T> T.serializeToJsonElement(json: Json = Json): JsonElement =
210+
json.encodeToJsonElement<T>(this)
222211

223212
/**
224213
* Serializes the [this] into an equivalent [JsonElement] using a serializer retrieved
225214
* from reified type parameter.
226215
* Returns `null` when on failure.
227216
*/
228-
inline fun <reified T> T.serializeToJsonElementOrNull(json: Json = Json): JsonElement? {
229-
return try {
230-
return json.encodeToJsonElement(this)
231-
} catch (_: SerializationException) {
232-
null
233-
}
234-
}
217+
@Deprecated(DEP_MSG, ReplaceWith("json.encodeToJsonElementOrNull<T>(this)"))
218+
inline fun <reified T> T.serializeToJsonElementOrNull(json: Json = Json): JsonElement? =
219+
json.encodeToJsonElementOrNull<T>(this)
235220

236221
/**
237222
* Serializes the [this] into an equivalent [JsonElement] using a serializer retrieved
238223
* from reified type parameter.
239224
*/
240-
inline fun <reified T> T.serializeToJsonElementCatching(json: Json = Json): Result<JsonElement> {
241-
return try {
242-
success(json.encodeToJsonElement(this))
243-
} catch (e: SerializationException) {
244-
failure(e)
245-
}
246-
}
225+
@Deprecated(DEP_MSG, ReplaceWith("runCatching { json.encodeToJsonElement<T>(this) }"))
226+
inline fun <reified T> T.serializeToJsonElementCatching(json: Json = Json): Result<JsonElement> =
227+
runCatching { json.encodeToJsonElement<T>(this) }
247228

248229
// T => JsonObject
249230

@@ -254,24 +235,23 @@ inline fun <reified T> T.serializeToJsonElementCatching(json: Json = Json): Resu
254235
* @throws [SerializationException] if the given value cannot be serialized to JSON.
255236
* @throws [ClassCastException] if the given value was not serialized to JsonObject.
256237
*/
257-
inline fun <reified T> T.serializeToJsonObject(json: Json = Json): JsonObject {
258-
return serializeToJsonElement(json) as JsonObject
259-
}
238+
@Deprecated(DEP_MSG, ReplaceWith("json.encodeToJsonElement<T>(this).asJsonObject"))
239+
inline fun <reified T> T.serializeToJsonObject(json: Json = Json): JsonObject =
240+
json.encodeToJsonElement<T>(this).asJsonObject
260241

261242
/**
262243
* Serializes the [this] into an equivalent [JsonObject] using a serializer retrieved
263244
* from reified type parameter.
264245
* Returns `null` when on failure.
265246
*/
266-
inline fun <reified T> T.serializeToJsonObjectOrNull(json: Json = Json): JsonObject? {
267-
return serializeToJsonElementOrNull(json) as? JsonObject
268-
}
247+
@Deprecated(DEP_MSG, ReplaceWith("json.encodeToJsonElementOrNull<T>(this)?.asJsonObjectOrNull"))
248+
inline fun <reified T> T.serializeToJsonObjectOrNull(json: Json = Json): JsonObject? =
249+
json.encodeToJsonElementOrNull<T>(this)?.asJsonObjectOrNull
269250

270251
/**
271252
* Serializes the [this] into an equivalent [JsonObject] using a serializer retrieved
272253
* from reified type parameter.
273254
*/
274-
inline fun <reified T> T.serializeToJsonObjectCatching(json: Json = Json): Result<JsonObject> {
275-
return serializeToJsonElementCatching(json)
276-
.mapCatching { it as JsonObject }
277-
}
255+
@Deprecated(DEP_MSG, ReplaceWith("runCatching { json.encodeToJsonElement<T>(this).asJsonObject }"))
256+
inline fun <reified T> T.serializeToJsonObjectCatching(json: Json = Json): Result<JsonObject> =
257+
runCatching { json.encodeToJsonElement<T>(this).asJsonObject }

0 commit comments

Comments
 (0)