Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 基于GSON的DSL导致NPE_Kotlin_Gson_Dsl - Fatal编程技术网

Kotlin 基于GSON的DSL导致NPE

Kotlin 基于GSON的DSL导致NPE,kotlin,gson,dsl,Kotlin,Gson,Dsl,我一直在尝试创建一个Kotlin DSL,用于使用类似JSON的语法创建GSON JSONObject。我的建筑工人看起来像这样 import com.google.gson.JsonArray import com.google.gson.JsonElement import com.google.gson.JsonObject import com.google.gson.JsonPrimitive class JsonBuilder(builder: JsonBuilder.() -&g

我一直在尝试创建一个Kotlin DSL,用于使用类似JSON的语法创建GSON JSONObject。我的建筑工人看起来像这样

import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive

class JsonBuilder(builder: JsonBuilder.() -> Unit) {
    init {
        builder()
    }

    val result = JsonObject()

    infix fun String.to(property: Number) = result.addProperty(this, property)
    infix fun String.to(property: Char) = result.addProperty(this, property)
    infix fun String.to(property: Boolean) = result.addProperty(this, property)
    infix fun String.to(property: String) = result.addProperty(this, property)
    infix fun String.to(property: JsonElement) = result.add(this, property)
    infix fun String.to(properties: Collection<JsonElement>) {
        val arr = JsonArray()
        properties.forEach(arr::add)
        result.add(this, arr)
    }
    operator fun String.invoke(builder: JsonObject.() -> Unit) {
        val obj = JsonObject()
        obj.builder()
        result.add(this, obj)
    }
}

fun json(builder: JsonBuilder.() -> Unit) = JsonBuilder(builder).result
fun main() {
    val json = json {
        "name" to "value"
        "obj" {
            "int" to 1
        }
        "true" to true
    }
    println(json)
}
但是,在执行时,它会导致一个指向所使用的第一个字符串扩展函数的NullPointerException,我认为这不是很好的描述,因为在这一点上我看不到任何可以为Null的东西。此外,我不认为它与常规执行有什么区别,因为常规执行当然不会导致NPE

    val json = JsonObject()
    json.addProperty("name", "value")
    val obj = JsonObject()
    obj.addProperty("int", 1)
    json.add("obj", obj)
    json.addProperty("true", true)

我的问题是到底是什么导致了异常(以及如何防止它)。

问题是您在result对象之前指定了initialiser块,这导致在使用它时它为null-这可以通过以下内容(代码的反编译输出)进行可视化

因此,解决方案是将结果的声明和初始化移到比初始化器块更早的位置

class JsonBuilder(builder: JsonBuilder.() -> Unit) {
    val result = JsonObject()

    init {
        builder()
    }

    // ...
}
结果是现在

{"name":"value","int":1,"obj":{},"true":true}
编辑:您还需要允许与DSL链接,并修复当前存在的错误

    operator fun String.invoke(builder: JsonBuilder.() -> Unit) {
        val obj = JsonBuilder(builder).result
        result.add(this, obj)
    }
这会产生正确的结果

{"name":"value","obj":{"int":1},"true":true}

哦谢谢我不知道那个命令在科特林很重要。
{"name":"value","obj":{"int":1},"true":true}