Sah*_*wal 0 scala nullable gson
我可以在 Scala 对象中有 Nullable 参数吗?
类似于 C# 中的 Nullable 和语法糖:
public int? Age {get; set;}
public string Name {get; set;}
public bool? isAdmin {get; set;}
Run Code Online (Sandbox Code Playgroud)
我可以创建 Scala 类,其中对象可以设置其中一些属性,而其他属性则不能吗?
我打算有多个构造函数用于不同的目的。我想确保空值意味着未设置该字段。
更新
例如我有以下案例类
case class Employee(age: Int, salary: Int, scaleNum : Int,
name: String, memberId: Int )
Run Code Online (Sandbox Code Playgroud)
我正在使用 GSON 序列化 JSON 中的类。
但是,在某些情况下,我不想为某些参数传递值,这样 GSON 序列化程序将只包含具有非 NULL 值的参数。
我怎样才能通过选项或其他方式实现这一目标?
对于您的示例,Scala 中的常见声明是:
case class Employee(
age: Option[Int], // For int? Age
name: String // For string Name
// your other decls ...
)
Run Code Online (Sandbox Code Playgroud)
然后您可以轻松使用该类型:
val john = Employee( age = Some(10), name = "John" )
Run Code Online (Sandbox Code Playgroud)
虽然 Scala 2 允许引用类型(如字符串等)为空值,但它从 Scala 3 开始慢慢改变(https://dotty.epfl.ch/docs/reference/other-new-features/explicit-nulls.html) .
Java 库(如 GSON)对 Scala 一无所知,因此您应该考虑使用其他支持 Scala 的 JSON 支持库:
这些库不仅Option[]在您的类定义中知道,而且还改进了对 Scala 集合、隐式、默认值和其他 Scala 语言功能的支持。
为此选择合适的库非常重要,因为使用 Java JSON 库,您最终会得到 Java 风格的类和代码,以及与其他 Scala 库的兼容性问题。
使用 Circe,您的示例将是:
import io.circe._
import io.circe.syntax._
import io.circe.parser._
import io.circe.generic.auto._
val john = Employee( age = Some(10), name = "John" )
val johnAsJson = john.asJson.dropNullValues
decode[Employee]( johnAsJson ) match {
case Right(johnBack) => ??? // johnBack now is the same as john
case Left(err) => ??? // handle JSON parse exceptions
}
Run Code Online (Sandbox Code Playgroud)
现在您可能正在寻找Scala 中的 Null 合并运算符(??在 C# 中,?在 Kotlin 中,...)的位置。
直接的答案 - 语言本身没有。在 Scala 中,我们以 FP 方式使用 Option(和其他一元结构,或 ADT)。
这意味着,例如:
case class Address(zip : Option[String])
case class Employee(
address: Option[Address]
)
val john = Employee( address = Some( Address( zip = Some("1111A") )) )
Run Code Online (Sandbox Code Playgroud)
你应该避免这种风格:
if (john.address.isDefined) {
if(john.address.zip.isDefined) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
你可以使用map/ flatMaps 代替:
john.address.flatMap { address =>
address.zip.map { zip =>
// your zip and address value
??
}
}
// or if you need only zip in a short form:
john.address.flatMap(_.zip).map { zip =>
// your zip value
??
}
Run Code Online (Sandbox Code Playgroud)
或for-comprehension语法(基于相同的 flatMaps):
for {
address <- john.address
zip <- address.zip
}
yield {
// doing something with zip and address
??
}
Run Code Online (Sandbox Code Playgroud)
重要的部分是在 Scala 中解决这个问题的惯用方法主要基于 FP 的模式。