Skip to content

Commit 6246e0a

Browse files
authored
Add functions for creating JsonPrimitives from unsigned numbers (#2160)
1 parent cbd8ce3 commit 6246e0a

File tree

3 files changed

+118
-10
lines changed

3 files changed

+118
-10
lines changed

formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonPrimitiveSerializerTest.kt

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,84 @@ class JsonPrimitiveSerializerTest : JsonTestBase() {
121121
assertEquals(string, jvmExpectedString)
122122
}
123123
}
124+
125+
/**
126+
* Helper function for [testJsonPrimitiveUnsignedNumbers]
127+
*
128+
* Asserts that an [unsigned number][actual] can be used to create a [JsonPrimitive][actualPrimitive],
129+
* which can be decoded correctly.
130+
*
131+
* @param expected the expected string value of [actual]
132+
* @param actual the unsigned number
133+
* @param T should be an unsigned number
134+
*/
135+
private inline fun <reified T> assertUnsignedNumberEncoding(
136+
expected: String,
137+
actual: T,
138+
actualPrimitive: JsonPrimitive,
139+
) {
140+
assertEquals(
141+
expected,
142+
actualPrimitive.toString(),
143+
"expect ${T::class.simpleName} $actual can be used to create a JsonPrimitive"
144+
)
145+
146+
parametrizedTest { mode ->
147+
assertEquals(
148+
expected,
149+
default.encodeToString(JsonElement.serializer(), actualPrimitive, mode),
150+
"expect ${T::class.simpleName} primitive can be decoded",
151+
)
152+
}
153+
}
154+
155+
@Test
156+
fun testJsonPrimitiveUnsignedNumbers() {
157+
158+
val expectedActualUBytes: Map<String, UByte> = mapOf(
159+
"0" to 0u,
160+
"1" to 1u,
161+
"255" to UByte.MAX_VALUE,
162+
)
163+
164+
expectedActualUBytes.forEach { (expected, actual) ->
165+
assertUnsignedNumberEncoding(expected, actual, JsonPrimitive(actual))
166+
}
167+
168+
val expectedActualUShorts: Map<String, UShort> = mapOf(
169+
"0" to 0u,
170+
"1" to 1u,
171+
"255" to UByte.MAX_VALUE.toUShort(),
172+
"65535" to UShort.MAX_VALUE,
173+
)
174+
175+
expectedActualUShorts.forEach { (expected, actual) ->
176+
assertUnsignedNumberEncoding(expected, actual, JsonPrimitive(actual))
177+
}
178+
179+
val expectedActualUInts: Map<String, UInt> = mapOf(
180+
"0" to 0u,
181+
"1" to 1u,
182+
"255" to UByte.MAX_VALUE.toUInt(),
183+
"65535" to UShort.MAX_VALUE.toUInt(),
184+
"4294967295" to UInt.MAX_VALUE,
185+
)
186+
187+
expectedActualUInts.forEach { (expected, actual) ->
188+
assertUnsignedNumberEncoding(expected, actual, JsonPrimitive(actual))
189+
}
190+
191+
val expectedActualULongs: Map<String, ULong> = mapOf(
192+
"0" to 0u,
193+
"1" to 1u,
194+
"255" to UByte.MAX_VALUE.toULong(),
195+
"65535" to UShort.MAX_VALUE.toULong(),
196+
"4294967295" to UInt.MAX_VALUE.toULong(),
197+
"18446744073709551615" to ULong.MAX_VALUE,
198+
)
199+
200+
expectedActualULongs.forEach { (expected, actual) ->
201+
assertUnsignedNumberEncoding(expected, actual, JsonPrimitive(actual))
202+
}
203+
}
124204
}

formats/json/api/kotlinx-serialization-json.api

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@ public final class kotlinx/serialization/json/JsonElementKt {
190190
public static final fun JsonPrimitive (Ljava/lang/Number;)Lkotlinx/serialization/json/JsonPrimitive;
191191
public static final fun JsonPrimitive (Ljava/lang/String;)Lkotlinx/serialization/json/JsonPrimitive;
192192
public static final fun JsonPrimitive (Ljava/lang/Void;)Lkotlinx/serialization/json/JsonNull;
193+
public static final fun JsonPrimitive-7apg3OU (B)Lkotlinx/serialization/json/JsonPrimitive;
194+
public static final fun JsonPrimitive-VKZWuLQ (J)Lkotlinx/serialization/json/JsonPrimitive;
195+
public static final fun JsonPrimitive-WZ4Q5Ns (I)Lkotlinx/serialization/json/JsonPrimitive;
196+
public static final fun JsonPrimitive-xj2QHRw (S)Lkotlinx/serialization/json/JsonPrimitive;
193197
public static final fun JsonUnquotedLiteral (Ljava/lang/String;)Lkotlinx/serialization/json/JsonPrimitive;
194198
public static final fun getBoolean (Lkotlinx/serialization/json/JsonPrimitive;)Z
195199
public static final fun getBooleanOrNull (Lkotlinx/serialization/json/JsonPrimitive;)Ljava/lang/Boolean;

formats/json/commonMain/src/kotlinx/serialization/json/JsonElement.kt

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,33 +49,57 @@ public sealed class JsonPrimitive : JsonElement() {
4949
public override fun toString(): String = content
5050
}
5151

52-
/**
53-
* Creates [JsonPrimitive] from the given boolean.
54-
*/
52+
/** Creates a [JsonPrimitive] from the given boolean. */
5553
public fun JsonPrimitive(value: Boolean?): JsonPrimitive {
5654
if (value == null) return JsonNull
5755
return JsonLiteral(value, isString = false)
5856
}
5957

60-
/**
61-
* Creates [JsonPrimitive] from the given number.
62-
*/
58+
/** Creates a [JsonPrimitive] from the given number. */
6359
public fun JsonPrimitive(value: Number?): JsonPrimitive {
6460
if (value == null) return JsonNull
6561
return JsonLiteral(value, isString = false)
6662
}
6763

6864
/**
69-
* Creates [JsonPrimitive] from the given string.
65+
* Creates a numeric [JsonPrimitive] from the given [UByte].
66+
*
67+
* The value will be encoded as a JSON number.
68+
*/
69+
@ExperimentalSerializationApi
70+
public fun JsonPrimitive(value: UByte): JsonPrimitive = JsonPrimitive(value.toULong())
71+
72+
/**
73+
* Creates a numeric [JsonPrimitive] from the given [UShort].
74+
*
75+
* The value will be encoded as a JSON number.
76+
*/
77+
@ExperimentalSerializationApi
78+
public fun JsonPrimitive(value: UShort): JsonPrimitive = JsonPrimitive(value.toULong())
79+
80+
/**
81+
* Creates a numeric [JsonPrimitive] from the given [UInt].
82+
*
83+
* The value will be encoded as a JSON number.
84+
*/
85+
@ExperimentalSerializationApi
86+
public fun JsonPrimitive(value: UInt): JsonPrimitive = JsonPrimitive(value.toULong())
87+
88+
/**
89+
* Creates a numeric [JsonPrimitive] from the given [ULong].
90+
*
91+
* The value will be encoded as a JSON number.
7092
*/
93+
@ExperimentalSerializationApi
94+
public fun JsonPrimitive(value: ULong): JsonPrimitive = JsonUnquotedLiteral(value.toString())
95+
96+
/** Creates a [JsonPrimitive] from the given string. */
7197
public fun JsonPrimitive(value: String?): JsonPrimitive {
7298
if (value == null) return JsonNull
7399
return JsonLiteral(value, isString = true)
74100
}
75101

76-
/**
77-
* Creates [JsonNull].
78-
*/
102+
/** Creates [JsonNull]. */
79103
@ExperimentalSerializationApi
80104
@Suppress("FunctionName", "UNUSED_PARAMETER") // allows to call `JsonPrimitive(null)`
81105
public fun JsonPrimitive(value: Nothing?): JsonNull = JsonNull

0 commit comments

Comments
 (0)