内置类¶
This is the second chapter of the Kotlin Serialization Guide. In addition to all the primitive types and strings, serialization for some classes from the Kotlin standard library, including the standard collections, is built into Kotlin Serialization. This chapter explains the details.
这是《Kotlin 序列化指南》的第二章。除了所有基元类型和字符串之外,Kotlin 标准库中某些类(包括标准集合)的序列化也内置于 Kotlin 序列化中。本章将介绍详细信息。
基本数据类型)¶
Primitives
Kotlin Serialization has the following ten primitives: Boolean
, Byte
, Short
, Int
, Long
, Float
, Double
, Char
, String
, and enums. The other types in Kotlin Serialization are composite—composed of those primitive values.
Kotlin 序列化包含以下十个基元: Boolean
, Byte
, Short
, Int
, Long
, Float
, Double
, Char
, String
Kotlin 序列化中的其他类型是复合的,由这些基元值组成。
数字¶
Numbers
All types of integer and floating-point Kotlin numbers can be serialized.
所有类型的整数和浮点 Kotlin 数字都可以序列化。
@Serializable
class Data(
val answer: Int,
val pi: Double
)
fun main() {
val data = Data(42, PI)
println(Json.encodeToString(data))
}
You can get the full code here.
您可以在此处获取完整代码。
Their natural representation in JSON is used.
使用它们在 JSON 中的自然表示形式。
长数字¶
Long numbers
Long integers are serializable, too.
长整数也是可序列化的。
@Serializable
class Data(val signature: Long)
fun main() {
val data = Data(0x1CAFE2FEED0BABE0)
println(Json.encodeToString(data))
}
You can get the full code here.
您可以在此处获取完整代码。
By default they are serialized to JSON as numbers.
默认情况下,它们作为数字序列化为 JSON。
长数字作为字符串¶
Long numbers as strings
The JSON output from the previous example will get decoded normally by Kotlin Serialization running on Kotlin/JS. However, if we try to parse this JSON by native JavaScript methods, we get this truncated result.
上一个示例的 JSON 输出将由在 Kotlin/JS 上运行的 Kotlin 序列化正常解码。但是,如果我们尝试通过原生 JavaScript 方法解析此 JSON,我们会得到这个截断的结果。
The full range of a Kotlin Long does not fit in the JavaScript number, so its precision gets lost in JavaScript. A common workaround is to represent long numbers with full precision using the JSON string type. This approach is optionally supported by Kotlin Serialization with LongAsStringSerializer, which can be specified for a given Long property using the @Serializable
annotation:
Kotlin Long 的完整范围不适合 JavaScript 编号,因此其精度在 JavaScript 中丢失。一种常见的解决方法是使用 JSON 字符串类型以完全精度表示长数字。此方法可由 Kotlin Serialization with LongAsStringSerializer 选择性地支持,可以使用以下 @Serializable
注释为给定的 Long 属性指定此方法:
@Serializable
class Data(
@Serializable(with=LongAsStringSerializer::class)
val signature: Long
)
fun main() {
val data = Data(0x1CAFE2FEED0BABE0)
println(Json.encodeToString(data))
}
You can get the full code here.
您可以在此处获取完整代码。
This JSON gets parsed natively by JavaScript without loss of precision.
此 JSON 由 JavaScript 本机解析,而不会损失精度。
The section on Specifying serializers for a file explains how a serializer like
LongAsStringSerializer
can be specified for all properties in a file.
为文件指定序列化程序一节介绍了如何为文件中的所有属性指定序列化程序。LongAsStringSerializer
枚举类¶
Enum classes
All enum classes are serializable out of the box without having to mark them @Serializable
, as the following example shows.
所有枚举类都是开箱即用的可序列化,无需标记它们 @Serializable
,如以下示例所示。
// The @Serializable annotation is not needed for enum classes
enum class Status { SUPPORTED }
@Serializable
class Project(val name: String, val status: Status)
fun main() {
val data = Project("kotlinx.serialization", Status.SUPPORTED)
println(Json.encodeToString(data))
}
You can get the full code here.
您可以在此处获取完整代码。
In JSON an enum gets encoded as a string.
在 JSON 中,枚举被编码为字符串。
Note: On Kotlin/JS and Kotlin/Native,
@Serializable
annotation is needed for enum class if you want to use it as a root object — i.e. useencodeToString<Status>(Status.SUPPORTED)
.
注意:在 Kotlin/JS 和 Kotlin/Native 上,@Serializable
如果您想将枚举类用作根对象,则需要对枚举类进行注释——即使用encodeToString<Status>(Status.SUPPORTED)
.
枚举类的序列化名¶
Serial names of enum entries
Serial names of enum entries can be customized with the SerialName annotation just like it was shown for properties in the Serial field names section. However, in this case, the whole enum class must be marked with the @Serializable
annotation.
可以使用 SerialName 注解自定义枚举条目的序列化名称,就像在“串行字段名称”部分中为属性显示的那样。但是,在这种情况下,必须用 @Serializable
注释标记整个枚举类。
@Serializable // required because of @SerialName
enum class Status { @SerialName("maintained") SUPPORTED }
@Serializable
class Project(val name: String, val status: Status)
fun main() {
val data = Project("kotlinx.serialization", Status.SUPPORTED)
println(Json.encodeToString(data))
}
You can get the full code here.
您可以在此处获取完整代码。
We see that the specified serial name is now used in the resulting JSON.
我们看到,在生成的 JSON 中现在使用了指定的序列化名称。
复合类型¶
Composites
A number of composite types from the standard library are supported by Kotlin Serialization.
Kotlin 序列化支持标准库中的许多复合类型。
Pair and triple¶
The simple data classes Pair and Triple from the Kotlin standard library are serializable.
Kotlin 标准库中的简单数据类 Pair 和 Triple 是可序列化的。
@Serializable
class Project(val name: String)
fun main() {
val pair = 1 to Project("kotlinx.serialization")
println(Json.encodeToString(pair))
}
You can get the full code here.
您可以在此处获取完整代码。
Not all classes from the Kotlin standard library are serializable. In particular, ranges and the Regex class are not serializable at the moment. Support for their serialization may be added in the future.
并非 Kotlin 标准库中的所有类都是可序列化的。特别是,范围和正则表达式类目前不可序列化。将来可能会添加对其序列化的支持。
Lists¶
A List of serializable classes can be serialized.
可以序列化可序列化类的列表。
@Serializable
class Project(val name: String)
fun main() {
val list = listOf(
Project("kotlinx.serialization"),
Project("kotlinx.coroutines")
)
println(Json.encodeToString(list))
}
You can get the full code here.
您可以在此处获取完整代码。
The result is represented as a list in JSON.
结果以 JSON 形式表示为列表。
Sets and other collections¶
Other collections, like Set, are also serializable.
其他集合(如 Set)也是可序列化的。
@Serializable
class Project(val name: String)
fun main() {
val set = setOf(
Project("kotlinx.serialization"),
Project("kotlinx.coroutines")
)
println(Json.encodeToString(set))
}
You can get the full code here.
您可以在此处获取完整代码。
Set is also represented as a list in JSON, like all other collections.
与所有其他集合一样,Set 也以 JSON 表示为列表。
Deserializing collections 反序列化集合¶
During deserialization, the type of the resulting object is determined by the static type that was specified in the source code—either as the type of the property or as the type parameter of the decoding function. The following example shows how the same JSON list of integers is deserialized into two properties of different Kotlin types.
在反序列化过程中,生成对象的类型由源代码中指定的静态类型确定,该类型可以是属性的类型,也可以是解码函数的类型参数。以下示例显示了如何将相同的整数 JSON 列表反序列化为不同 Kotlin 类型的两个属性。
@Serializable
data class Data(
val a: List<Int>,
val b: Set<Int>
)
fun main() {
val data = Json.decodeFromString<Data>("""
{
"a": [42, 42],
"b": [42, 42]
}
""")
println(data)
}
You can get the full code here.
您可以在此处获取完整代码。
Because the data.b
property is a Set, the duplicate values from it disappeared.
由于该 data.b
属性是 Set,因此该属性中的重复值将消失。
Maps¶
A Map with primitive or enum keys and arbitrary serializable values can be serialized.
可以序列化具有基元或枚举键以及任意可序列化值的映射。
@Serializable
class Project(val name: String)
fun main() {
val map = mapOf(
1 to Project("kotlinx.serialization"),
2 to Project("kotlinx.coroutines")
)
println(Json.encodeToString(map))
}
You can get the full code here.
您可以在此处获取完整代码。
Kotlin maps in JSON are represented as objects. In JSON object keys are always strings, so keys are encoded as strings even if they are numbers in Kotlin, as we can see below.
JSON 中的 Kotlin 地图表示为对象。在 JSON 对象中,键始终是字符串,因此键被编码为字符串,即使它们在 Kotlin 中是数字,如下图所示。
It is a JSON-specific limitation that keys cannot be composite. It can be lifted as shown in the Allowing structured map keys section.
键不能是复合的,这是特定于 JSON 的限制。可以按照允许结构化映射键部分中所示的方式将其解除。
Unit and singleton objects Unit和单例对象¶
The Kotlin builtin Unit
type is also serializable. Unit
is a Kotlin singleton object, and is handled equally with other Kotlin objects.
Kotlin 内置 Unit
类型也是可序列化的。 Unit
是一个 Kotlin 单例对象,与其他 Kotlin 对象处理方式相同。
Conceptually, a singleton is a class with only one instance, meaning that state does not define the object, but the object defines its state. In JSON, objects are serialized as empty structures.
从概念上讲,单例是一个只有一个实例的类,这意味着状态不定义对象,但对象定义其状态。在 JSON 中,对象被序列化为空结构。
@Serializable
object SerializationVersion {
val libraryVersion: String = "1.0.0"
}
fun main() {
println(Json.encodeToString(SerializationVersion))
println(Json.encodeToString(Unit))
}
You can get the full code here.
您可以在此处获取完整代码。
While it may seem useless at first glance, this comes in handy for sealed class serialization, which is explained in the Polymorphism. Objects section.
虽然乍一看似乎毫无用处,但这对于密封类序列化非常有用,这在多态性中进行了解释。“对象”部分。
Serialization of objects is format specific. Other formats may represent objects differently, e.g. using their fully-qualified names.
对象的序列化是特定于格式的。其他格式可能以不同的方式表示对象,例如使用其完全限定的名称。
Duration¶
Since Kotlin 1.7.20
the Duration class has become serializable.
从 Kotlin 1.7.20
开始,Duration 类变得可序列化。
fun main() {
val duration = 1000.toDuration(DurationUnit.SECONDS)
println(Json.encodeToString(duration))
}
You can get the full code here.
您可以在此处获取完整代码。
Duration is serialized as a string in the ISO-8601-2 format.
持续时间以 ISO-8601-2 格式序列化为字符串。
Nothing¶
By default, Nothing is a serializable class. However, since there are no instances of this class, it is impossible to encode or decode its values - any attempt will cause an exception.
默认情况下,Nothing 是可序列化的类。但是,由于没有此类的实例,因此无法对其值进行编码或解码 - 任何尝试都会导致异常。
This serializer is used when syntactically some type is needed, but it is not actually used in serialization. For example, when using parameterized polymorphic base classes:
当语法上需要某种类型时,会使用此序列化程序,但实际上并未在序列化中使用。例如,使用参数化多态基类时:
@Serializable
sealed class ParametrizedParent<out R> {
@Serializable
data class ChildWithoutParameter(val value: Int) : ParametrizedParent<Nothing>()
}
fun main() {
println(Json.encodeToString(ParametrizedParent.ChildWithoutParameter(42)))
}
You can get the full code here.
您可以在此处获取完整代码。
When encoding, the serializer for the Nothing
was not used
编码时,未使用 的 Nothing
The next chapter covers Serializers.
下一章将介绍序列化程序。