Skip to content

Commit aedd915

Browse files
authored
Allow Kotlin's null literal in JSON DSL (#1907)
1 parent 1cff25e commit aedd915

File tree

4 files changed

+41
-12
lines changed

4 files changed

+41
-12
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,15 @@ public final class kotlinx/serialization/json/JsonElementBuildersKt {
169169
public static final fun add (Lkotlinx/serialization/json/JsonArrayBuilder;Ljava/lang/Boolean;)Z
170170
public static final fun add (Lkotlinx/serialization/json/JsonArrayBuilder;Ljava/lang/Number;)Z
171171
public static final fun add (Lkotlinx/serialization/json/JsonArrayBuilder;Ljava/lang/String;)Z
172+
public static final fun add (Lkotlinx/serialization/json/JsonArrayBuilder;Ljava/lang/Void;)Z
172173
public static final fun addJsonArray (Lkotlinx/serialization/json/JsonArrayBuilder;Lkotlin/jvm/functions/Function1;)Z
173174
public static final fun addJsonObject (Lkotlinx/serialization/json/JsonArrayBuilder;Lkotlin/jvm/functions/Function1;)Z
174175
public static final fun buildJsonArray (Lkotlin/jvm/functions/Function1;)Lkotlinx/serialization/json/JsonArray;
175176
public static final fun buildJsonObject (Lkotlin/jvm/functions/Function1;)Lkotlinx/serialization/json/JsonObject;
176177
public static final fun put (Lkotlinx/serialization/json/JsonObjectBuilder;Ljava/lang/String;Ljava/lang/Boolean;)Lkotlinx/serialization/json/JsonElement;
177178
public static final fun put (Lkotlinx/serialization/json/JsonObjectBuilder;Ljava/lang/String;Ljava/lang/Number;)Lkotlinx/serialization/json/JsonElement;
178179
public static final fun put (Lkotlinx/serialization/json/JsonObjectBuilder;Ljava/lang/String;Ljava/lang/String;)Lkotlinx/serialization/json/JsonElement;
180+
public static final fun put (Lkotlinx/serialization/json/JsonObjectBuilder;Ljava/lang/String;Ljava/lang/Void;)Lkotlinx/serialization/json/JsonElement;
179181
public static final fun putJsonArray (Lkotlinx/serialization/json/JsonObjectBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lkotlinx/serialization/json/JsonElement;
180182
public static final fun putJsonObject (Lkotlinx/serialization/json/JsonObjectBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lkotlinx/serialization/json/JsonElement;
181183
}
@@ -184,6 +186,7 @@ public final class kotlinx/serialization/json/JsonElementKt {
184186
public static final fun JsonPrimitive (Ljava/lang/Boolean;)Lkotlinx/serialization/json/JsonPrimitive;
185187
public static final fun JsonPrimitive (Ljava/lang/Number;)Lkotlinx/serialization/json/JsonPrimitive;
186188
public static final fun JsonPrimitive (Ljava/lang/String;)Lkotlinx/serialization/json/JsonPrimitive;
189+
public static final fun JsonPrimitive (Ljava/lang/Void;)Lkotlinx/serialization/json/JsonNull;
187190
public static final fun getBoolean (Lkotlinx/serialization/json/JsonPrimitive;)Z
188191
public static final fun getBooleanOrNull (Lkotlinx/serialization/json/JsonPrimitive;)Ljava/lang/Boolean;
189192
public static final fun getContentOrNull (Lkotlinx/serialization/json/JsonPrimitive;)Ljava/lang/String;

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ public fun JsonPrimitive(value: String?): JsonPrimitive {
6969
return JsonLiteral(value, isString = true)
7070
}
7171

72+
/**
73+
* Creates [JsonNull].
74+
*/
75+
@ExperimentalSerializationApi
76+
@Suppress("FunctionName", "UNUSED_PARAMETER") // allows to call `JsonPrimitive(null)`
77+
public fun JsonPrimitive(value: Nothing?): JsonNull = JsonNull
78+
7279
// JsonLiteral is deprecated for public use and no longer available. Please use JsonPrimitive instead
7380
internal class JsonLiteral internal constructor(
7481
body: Any,

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

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package kotlinx.serialization.json
77

8+
import kotlinx.serialization.ExperimentalSerializationApi
89
import kotlin.contracts.*
910

1011
/**
@@ -72,15 +73,15 @@ public class JsonObjectBuilder @PublishedApi internal constructor() {
7273
}
7374

7475
/**
75-
* Add the [JSON][JsonObject] produced by the [builderAction] function to a resulting json object using the given [key].
76+
* Add the [JSON object][JsonObject] produced by the [builderAction] function to a resulting JSON object using the given [key].
7677
*
7778
* Returns the previous value associated with [key], or `null` if the key was not present.
7879
*/
7980
public fun JsonObjectBuilder.putJsonObject(key: String, builderAction: JsonObjectBuilder.() -> Unit): JsonElement? =
8081
put(key, buildJsonObject(builderAction))
8182

8283
/**
83-
* Add the [JSON array][JsonArray] produced by the [builderAction] function to a resulting json object using the given [key].
84+
* Add the [JSON array][JsonArray] produced by the [builderAction] function to a resulting JSON object using the given [key].
8485
*
8586
* Returns the previous value associated with [key], or `null` if the key was not present.
8687
*/
@@ -108,6 +109,15 @@ public fun JsonObjectBuilder.put(key: String, value: Number?): JsonElement? = pu
108109
*/
109110
public fun JsonObjectBuilder.put(key: String, value: String?): JsonElement? = put(key, JsonPrimitive(value))
110111

112+
/**
113+
* Add `null` to a resulting JSON object using the given [key].
114+
*
115+
* Returns the previous value associated with [key], or `null` if the key was not present.
116+
*/
117+
@ExperimentalSerializationApi
118+
@Suppress("UNUSED_PARAMETER") // allows to call `put("key", null)`
119+
public fun JsonObjectBuilder.put(key: String, value: Nothing?): JsonElement? = put(key, JsonNull)
120+
111121
/**
112122
* DSL builder for a [JsonArray]. To create an instance of builder, use [buildJsonArray] build function.
113123
*/
@@ -117,7 +127,7 @@ public class JsonArrayBuilder @PublishedApi internal constructor() {
117127
private val content: MutableList<JsonElement> = mutableListOf()
118128

119129
/**
120-
* Adds the given JSON [element] to a resulting array.
130+
* Adds the given JSON [element] to a resulting JSON array.
121131
*
122132
* Always returns `true` similarly to [ArrayList] specification.
123133
*/
@@ -131,44 +141,51 @@ public class JsonArrayBuilder @PublishedApi internal constructor() {
131141
}
132142

133143
/**
134-
* Adds the given boolean [value] to a resulting array.
144+
* Adds the given boolean [value] to a resulting JSON array.
135145
*
136146
* Always returns `true` similarly to [ArrayList] specification.
137147
*/
138148
public fun JsonArrayBuilder.add(value: Boolean?): Boolean = add(JsonPrimitive(value))
139149

140150
/**
141-
* Adds the given numeric [value] to a resulting array.
151+
* Adds the given numeric [value] to a resulting JSON array.
142152
*
143153
* Always returns `true` similarly to [ArrayList] specification.
144154
*/
145155
public fun JsonArrayBuilder.add(value: Number?): Boolean = add(JsonPrimitive(value))
146156

147157
/**
148-
* Adds the given string [value] to a resulting array.
158+
* Adds the given string [value] to a resulting JSON array.
149159
*
150160
* Always returns `true` similarly to [ArrayList] specification.
151161
*/
152162
public fun JsonArrayBuilder.add(value: String?): Boolean = add(JsonPrimitive(value))
153163

154164
/**
155-
* Adds the [JSON][JsonObject] produced by the [builderAction] function to a resulting array.
165+
* Adds `null` to a resulting JSON array.
166+
*
167+
* Always returns `true` similarly to [ArrayList] specification.
168+
*/
169+
@ExperimentalSerializationApi
170+
@Suppress("UNUSED_PARAMETER") // allows to call `add(null)`
171+
public fun JsonArrayBuilder.add(value: Nothing?): Boolean = add(JsonNull)
172+
173+
/**
174+
* Adds the [JSON object][JsonObject] produced by the [builderAction] function to a resulting JSON array.
156175
*
157176
* Always returns `true` similarly to [ArrayList] specification.
158177
*/
159178
public fun JsonArrayBuilder.addJsonObject(builderAction: JsonObjectBuilder.() -> Unit): Boolean =
160179
add(buildJsonObject(builderAction))
161180

162181
/**
163-
* Adds the [JSON][JsonArray] produced by the [builderAction] function to a resulting array.
182+
* Adds the [JSON array][JsonArray] produced by the [builderAction] function to a resulting JSON array.
164183
*
165184
* Always returns `true` similarly to [ArrayList] specification.
166185
*/
167186
public fun JsonArrayBuilder.addJsonArray(builderAction: JsonArrayBuilder.() -> Unit): Boolean =
168187
add(buildJsonArray(builderAction))
169188

170-
private const val infixToDeprecated = "Infix 'to' operator is deprecated for removal for the favour of 'add'"
171-
private const val unaryPlusDeprecated = "Unary plus is deprecated for removal for the favour of 'add'"
172189

173190
@DslMarker
174191
internal annotation class JsonDslMarker

formats/json/commonTest/src/kotlinx/serialization/json/JsonBuildersTest.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ class JsonBuildersTest {
2424
put("primitive", JsonPrimitive(42))
2525
put("boolean", true)
2626
put("literal", "foo")
27+
put("null2", null)
2728
}
28-
assertEquals("""{"object":{"k":"v"},"array":[{"nestedLiteral":true}],"null":null,"primitive":42,"boolean":true,"literal":"foo"}""", json.toString())
29+
assertEquals("""{"object":{"k":"v"},"array":[{"nestedLiteral":true}],"null":null,"primitive":42,"boolean":true,"literal":"foo","null2":null}""", json.toString())
2930
}
3031

3132
@Test
@@ -35,10 +36,11 @@ class JsonBuildersTest {
3536
addJsonArray {
3637
for (i in 1..10) add(i)
3738
}
39+
add(null)
3840
addJsonObject {
3941
put("stringKey", "stringValue")
4042
}
4143
}
42-
assertEquals("""[true,[1,2,3,4,5,6,7,8,9,10],{"stringKey":"stringValue"}]""", json.toString())
44+
assertEquals("""[true,[1,2,3,4,5,6,7,8,9,10],null,{"stringKey":"stringValue"}]""", json.toString())
4345
}
4446
}

0 commit comments

Comments
 (0)