为什么 Moshi 在使用 fromJson 解析 json 时返回可为 null 的对象?

Wob*_*ley 5 kotlin moshi

这可能只是我用错了,因为我是 Kotlin 和 Moshi 的新手。

data class InitialAppResult(val status: Int, val message: String, val baseprm: String)

val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()  
val adapter = moshi.adapter(InitialAppResult::class.java)
val fromJson = adapter.fromJson(result.get())
Run Code Online (Sandbox Code Playgroud)

为什么 fromJson 可以为 null 并且需要 !! 或者 ?。例如:fromJson!!.baseprm

如果解析失败且缺少必填字段,则在我的情况下只会引发异常。那么它如何解析“无效”的 JSON 响应而不失败,即返回 null?

use*_*612 5

Moshi 是一个用 Java 实现的库,而您的代码是用 Kotlin 编写的。引用文档的“从 Kotlin 调用 Java 代码”部分:

Java 中的任何引用都可能为 null,这使得 Kotlin 严格的 null 安全要求对于来自 Java 的对象来说不切实际。

这意味着来自 Java 的任何对象默认情况下都可以为空。但是,如果您声明一个变量具有不可为 null 的类型,Kotlin 会自动“强制转换”它:

当平台值 [即本例中的 Java 对象] 被分配给 Kotlin 变量时,我们可以依赖类型推断(然后该变量将具有推断的平台类型,如上面示例中的 item 所示),或者我们可以选择我们期望的类型(可空类型和非空类型都允许)。

这是一个示例(同样来自上面链接的文档),其中item是一个 Java 对象:

val nullable: String? = item // allowed, always works
val notNull: String = item // allowed, may fail at runtime
Run Code Online (Sandbox Code Playgroud)

因此,在您的情况下,您可以通过键入以下内容强制对象不可为空:

val fromJson: InitialAppResult = adapter.fromJson(result.get())
Run Code Online (Sandbox Code Playgroud)

编辑

在这种情况下,所有fromJson方法都定义为@Nullable(作为null有效的 JSON 值),这意味着结果可以是null,因此推断的类型可以为空。这同样适用于@NotNull. 因此,这些注释对于 Java 和 Kotlin 之间的互操作性非常有用。

在其他情况下,如果缺少@Nullable@NotNull注释,则上面关于显式将值添加到变量的说法是正确的。

编辑 21/07/2020

为什么fromJson标记为@Nullable

原因是这null是一个有效的 JSON 值。以下示例都是有效的 JSON 字符串:

  • null
  • { "key": null }

因此,JsonAdapter需要能够处理null价值观。例如,以下是内置ObjectJsonAdapter函数如何处理nulls:

@Override public Object fromJson(JsonReader reader) throws IOException {
    ...
    case NULL:
      return reader.nextNull();
}
Run Code Online (Sandbox Code Playgroud)

这依赖于nextNull,其文档说:

使用 JSON 流中的下一个标记并断言它是文字 null。返回空值。