Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Kotlin's null literal in JSON DSL #1907

Merged
merged 8 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions formats/json/api/kotlinx-serialization-json.api
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,15 @@ public final class kotlinx/serialization/json/JsonElementBuildersKt {
public static final fun add (Lkotlinx/serialization/json/JsonArrayBuilder;Ljava/lang/Boolean;)Z
public static final fun add (Lkotlinx/serialization/json/JsonArrayBuilder;Ljava/lang/Number;)Z
public static final fun add (Lkotlinx/serialization/json/JsonArrayBuilder;Ljava/lang/String;)Z
public static final fun add (Lkotlinx/serialization/json/JsonArrayBuilder;Ljava/lang/Void;)Z
public static final fun addJsonArray (Lkotlinx/serialization/json/JsonArrayBuilder;Lkotlin/jvm/functions/Function1;)Z
public static final fun addJsonObject (Lkotlinx/serialization/json/JsonArrayBuilder;Lkotlin/jvm/functions/Function1;)Z
public static final fun buildJsonArray (Lkotlin/jvm/functions/Function1;)Lkotlinx/serialization/json/JsonArray;
public static final fun buildJsonObject (Lkotlin/jvm/functions/Function1;)Lkotlinx/serialization/json/JsonObject;
public static final fun put (Lkotlinx/serialization/json/JsonObjectBuilder;Ljava/lang/String;Ljava/lang/Boolean;)Lkotlinx/serialization/json/JsonElement;
public static final fun put (Lkotlinx/serialization/json/JsonObjectBuilder;Ljava/lang/String;Ljava/lang/Number;)Lkotlinx/serialization/json/JsonElement;
public static final fun put (Lkotlinx/serialization/json/JsonObjectBuilder;Ljava/lang/String;Ljava/lang/String;)Lkotlinx/serialization/json/JsonElement;
public static final fun put (Lkotlinx/serialization/json/JsonObjectBuilder;Ljava/lang/String;Ljava/lang/Void;)Lkotlinx/serialization/json/JsonElement;
public static final fun putJsonArray (Lkotlinx/serialization/json/JsonObjectBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lkotlinx/serialization/json/JsonElement;
public static final fun putJsonObject (Lkotlinx/serialization/json/JsonObjectBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lkotlinx/serialization/json/JsonElement;
}
Expand All @@ -184,6 +186,7 @@ public final class kotlinx/serialization/json/JsonElementKt {
public static final fun JsonPrimitive (Ljava/lang/Boolean;)Lkotlinx/serialization/json/JsonPrimitive;
public static final fun JsonPrimitive (Ljava/lang/Number;)Lkotlinx/serialization/json/JsonPrimitive;
public static final fun JsonPrimitive (Ljava/lang/String;)Lkotlinx/serialization/json/JsonPrimitive;
public static final fun JsonPrimitive (Ljava/lang/Void;)Lkotlinx/serialization/json/JsonNull;
public static final fun getBoolean (Lkotlinx/serialization/json/JsonPrimitive;)Z
public static final fun getBooleanOrNull (Lkotlinx/serialization/json/JsonPrimitive;)Ljava/lang/Boolean;
public static final fun getContentOrNull (Lkotlinx/serialization/json/JsonPrimitive;)Ljava/lang/String;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ public fun JsonPrimitive(value: String?): JsonPrimitive {
return JsonLiteral(value, isString = true)
}

/**
* Creates [JsonNull].
*/
@ExperimentalSerializationApi
@Suppress("FunctionName", "UNUSED_PARAMETER") // allows to call `JsonPrimitive(null)`
public fun JsonPrimitive(value: Nothing?): JsonNull = JsonNull

// JsonLiteral is deprecated for public use and no longer available. Please use JsonPrimitive instead
internal class JsonLiteral internal constructor(
body: Any,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package kotlinx.serialization.json

import kotlinx.serialization.ExperimentalSerializationApi
import kotlin.contracts.*

/**
Expand Down Expand Up @@ -72,15 +73,15 @@ public class JsonObjectBuilder @PublishedApi internal constructor() {
}

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

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

/**
* Add `null` to a resulting JSON object using the given [key].
*
* Returns the previous value associated with [key], or `null` if the key was not present.
*/
@ExperimentalSerializationApi
@Suppress("UNUSED_PARAMETER") // allows to call `put("key", null)`
public fun JsonObjectBuilder.put(key: String, value: Nothing?): JsonElement? = put(key, JsonNull)

/**
* DSL builder for a [JsonArray]. To create an instance of builder, use [buildJsonArray] build function.
*/
Expand All @@ -117,7 +127,7 @@ public class JsonArrayBuilder @PublishedApi internal constructor() {
private val content: MutableList<JsonElement> = mutableListOf()

/**
* Adds the given JSON [element] to a resulting array.
* Adds the given JSON [element] to a resulting JSON array.
*
* Always returns `true` similarly to [ArrayList] specification.
*/
Expand All @@ -131,44 +141,51 @@ public class JsonArrayBuilder @PublishedApi internal constructor() {
}

/**
* Adds the given boolean [value] to a resulting array.
* Adds the given boolean [value] to a resulting JSON array.
*
* Always returns `true` similarly to [ArrayList] specification.
*/
public fun JsonArrayBuilder.add(value: Boolean?): Boolean = add(JsonPrimitive(value))

/**
* Adds the given numeric [value] to a resulting array.
* Adds the given numeric [value] to a resulting JSON array.
*
* Always returns `true` similarly to [ArrayList] specification.
*/
public fun JsonArrayBuilder.add(value: Number?): Boolean = add(JsonPrimitive(value))

/**
* Adds the given string [value] to a resulting array.
* Adds the given string [value] to a resulting JSON array.
*
* Always returns `true` similarly to [ArrayList] specification.
*/
public fun JsonArrayBuilder.add(value: String?): Boolean = add(JsonPrimitive(value))

/**
* Adds the [JSON][JsonObject] produced by the [builderAction] function to a resulting array.
* Adds `null` to a resulting JSON array.
*
* Always returns `true` similarly to [ArrayList] specification.
*/
@ExperimentalSerializationApi
@Suppress("UNUSED_PARAMETER") // allows to call `add(null)`
public fun JsonArrayBuilder.add(value: Nothing?): Boolean = add(JsonNull)

/**
* Adds the [JSON object][JsonObject] produced by the [builderAction] function to a resulting JSON array.
*
* Always returns `true` similarly to [ArrayList] specification.
*/
public fun JsonArrayBuilder.addJsonObject(builderAction: JsonObjectBuilder.() -> Unit): Boolean =
add(buildJsonObject(builderAction))

/**
* Adds the [JSON][JsonArray] produced by the [builderAction] function to a resulting array.
* Adds the [JSON array][JsonArray] produced by the [builderAction] function to a resulting JSON array.
*
* Always returns `true` similarly to [ArrayList] specification.
*/
public fun JsonArrayBuilder.addJsonArray(builderAction: JsonArrayBuilder.() -> Unit): Boolean =
add(buildJsonArray(builderAction))

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

@DslMarker
internal annotation class JsonDslMarker
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ class JsonBuildersTest {
put("primitive", JsonPrimitive(42))
put("boolean", true)
put("literal", "foo")
put("null2", null)
}
assertEquals("""{"object":{"k":"v"},"array":[{"nestedLiteral":true}],"null":null,"primitive":42,"boolean":true,"literal":"foo"}""", json.toString())
assertEquals("""{"object":{"k":"v"},"array":[{"nestedLiteral":true}],"null":null,"primitive":42,"boolean":true,"literal":"foo","null2":null}""", json.toString())
}

@Test
Expand All @@ -35,10 +36,11 @@ class JsonBuildersTest {
addJsonArray {
for (i in 1..10) add(i)
}
add(null)
addJsonObject {
put("stringKey", "stringValue")
}
}
assertEquals("""[true,[1,2,3,4,5,6,7,8,9,10],{"stringKey":"stringValue"}]""", json.toString())
assertEquals("""[true,[1,2,3,4,5,6,7,8,9,10],null,{"stringKey":"stringValue"}]""", json.toString())
}
}