@@ -35,6 +35,39 @@ object JsoniterScalaCodec {
35
35
} else new JsonBigDecimal (in.readBigDecimal(null ).bigDecimal)
36
36
})
37
37
38
+ val defaultNumberSerializer : (JsonWriter , JsonNumber ) => Unit = (out : JsonWriter , x : JsonNumber ) => x match {
39
+ case l : JsonLong => out.writeVal(l.value)
40
+ case f : JsonFloat => out.writeVal(f.value)
41
+ case d : JsonDouble => out.writeVal(d.value)
42
+ case bd : JsonBigDecimal => out.writeVal(bd.value)
43
+ case _ => out.writeRawVal(x.toString.getBytes(StandardCharsets .UTF_8 ))
44
+ }
45
+
46
+ val jsCompatibleNumberSerializer : (JsonWriter , JsonNumber ) => Unit = (out : JsonWriter , x : JsonNumber ) => x match {
47
+ case l : JsonLong =>
48
+ val v = l.value
49
+ if (v >= - 4503599627370496L && v < 4503599627370496L ) out.writeVal(v)
50
+ else out.writeValAsString(v)
51
+ case f : JsonFloat => out.writeVal(f.value)
52
+ case d : JsonDouble => out.writeVal(d.value)
53
+ case bd : JsonBigDecimal =>
54
+ val v = bd.value
55
+ val bl = v.unscaledValue.bitLength
56
+ val s = v.scale
57
+ if (bl <= 52 && s >= - 256 && s <= 256 ) out.writeVal(v)
58
+ else out.writeValAsString(v)
59
+ case _ => x.toBigDecimal match {
60
+ case Some (bd) =>
61
+ val u = bd.underlying
62
+ val bl = u.unscaledValue.bitLength
63
+ val s = u.scale
64
+ if (bl <= 52 && s >= - 256 && s <= 256 ) out.writeVal(u)
65
+ else out.writeValAsString(u)
66
+ case _ =>
67
+ out.writeVal(x.toString)
68
+ }
69
+ }
70
+
38
71
/**
39
72
* Converts an ASCII byte array to a JSON string.
40
73
*
@@ -94,13 +127,27 @@ object JsoniterScalaCodec {
94
127
* @param initialSize the initial size hint for object and array collections
95
128
* @param doSerialize a predicate that determines whether a value should be serialized
96
129
* @param numberParser a function that parses JSON numbers
130
+ * @param numberSerializer a function that serializes JSON numbers
97
131
* @return The JSON codec
98
132
*/
99
133
final class JsoniterScalaCodec (
100
134
maxDepth : Int ,
101
135
initialSize : Int ,
102
136
doSerialize : Json => Boolean ,
103
- numberParser : JsonReader => Json ) extends JsonValueCodec [Json ] {
137
+ numberParser : JsonReader => Json ,
138
+ numberSerializer : (JsonWriter , JsonNumber ) => Unit ) extends JsonValueCodec [Json ] {
139
+
140
+ /**
141
+ * An auxiliary constructor for backward binary compatibility.
142
+ *
143
+ * @param maxDepth the maximum depth for decoding
144
+ * @param initialSize the initial size hint for object and array collections
145
+ * @param doSerialize a predicate that determines whether a value should be serialized
146
+ * @param numberParser a function that parses JSON numbers
147
+ */
148
+ def this (maxDepth : Int , initialSize : Int , doSerialize : Json => Boolean , numberParser : JsonReader => Json ) =
149
+ this (maxDepth, initialSize, doSerialize, numberParser, JsoniterScalaCodec .defaultNumberSerializer)
150
+
104
151
private [this ] val trueValue = True
105
152
private [this ] val falseValue = False
106
153
private [this ] val emptyArrayValue = new JArray (Vector .empty)
@@ -161,7 +208,7 @@ final class JsoniterScalaCodec(
161
208
if (str.length != 1 ) out.writeVal(str)
162
209
else out.writeVal(str.charAt(0 ))
163
210
case b : JBoolean => out.writeVal(b.value)
164
- case n : JNumber => encodeJsonNumber( n.value, out )
211
+ case n : JNumber => numberSerializer(out, n.value)
165
212
case a : JArray =>
166
213
val depthM1 = depth - 1
167
214
if (depthM1 < 0 ) out.encodeError(" depth limit exceeded" )
@@ -183,12 +230,4 @@ final class JsoniterScalaCodec(
183
230
out.writeObjectEnd()
184
231
case _ => out.writeNull()
185
232
}
186
-
187
- private [this ] def encodeJsonNumber (x : JsonNumber , out : JsonWriter ): Unit = x match {
188
- case l : JsonLong => out.writeVal(l.value)
189
- case f : JsonFloat => out.writeVal(f.value)
190
- case d : JsonDouble => out.writeVal(d.value)
191
- case bd : JsonBigDecimal => out.writeVal(bd.value)
192
- case _ => out.writeRawVal(x.toString.getBytes(StandardCharsets .UTF_8 ))
193
- }
194
233
}
0 commit comments