-
Notifications
You must be signed in to change notification settings - Fork 6
/
0033-CodingAsStream.kt
109 lines (84 loc) · 2.57 KB
/
0033-CodingAsStream.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package examples
import com.github.fluidsonic.fluid.json.*
import java.io.StringWriter
import java.time.Instant
object CodingAsStreamExample {
@JvmStatic
fun main(args: Array<String>) {
// Parsing and serialization using codecs is also supported when streaming by using JSONDecoder instead of
// JSONReader and JSONEncoder instead of JSONWriter
val input = listOf(
Event(id = 1, date = Instant.ofEpochSecond(1000000000), title = "One"),
Event(id = 2, date = Instant.ofEpochSecond(2000000000), title = "Two"),
Event(id = 3, date = Instant.ofEpochSecond(3000000000), title = "Three"),
Event(id = 4, date = Instant.ofEpochSecond(4000000000), title = "Four"),
Event(id = 5, date = Instant.ofEpochSecond(5000000000), title = "Five"),
Event(id = 6, title = "Six")
)
val json = encode(input)
val output = decode(json)
check(input == output) // to JSON and back!
println(output)
}
private fun decode(json: String) =
JSONDecoder.builder()
.codecs(EventCodec)
.source(json)
.build()
.use { decoder ->
val output = mutableListOf<Event>()
decoder.readListStart()
while (decoder.nextToken != JSONToken.listEnd) {
output.add(decoder.readValueOfType())
}
decoder.readListEnd()
return@use output
}
private fun encode(input: List<Event>): String {
val writer = StringWriter()
return JSONEncoder.builder()
.codecs(EventCodec)
.destination(writer)
.build()
.use { encoder ->
encoder.writeListStart()
for (event in input) {
encoder.writeValue(event)
}
encoder.writeListEnd()
return@use writer.toString()
}
}
private data class Event(
val id: Int,
val date: Instant? = null,
val title: String
)
private object EventCodec : AbstractJSONCodec<Event, JSONCoderContext>() {
override fun decode(valueType: JSONCodableType<in Event>, decoder: JSONDecoder<JSONCoderContext>): Event {
var id: Int? = null
var date: Instant? = null
var title: String? = null
decoder.readFromMapByElementValue { key ->
when (key) {
"id" -> id = readInt()
"date" -> date = readValueOfType()
"title" -> title = readString()
else -> skipValue()
}
}
return Event(
id = id ?: throw JSONException("missing id"),
date = date,
title = title ?: throw JSONException("missing title")
)
}
override fun encode(value: Event, encoder: JSONEncoder<JSONCoderContext>) {
encoder.writeIntoMap {
writeMapElement("id", int = value.id)
writeMapElement("date", value = value.date, skipIfNull = true)
writeMapElement("title", string = value.title)
}
}
}
}