@@ -14,26 +14,19 @@ import scala.collection.mutable
1414import scala .collection .mutable .ArrayBuffer
1515import scala .collection .mutable .ListBuffer
1616
17- import com .fasterxml .jackson .core .JsonFactoryBuilder
18- import com .fasterxml .jackson .core .JsonGenerator
19- import com .fasterxml .jackson .core .JsonParser
20- import com .fasterxml .jackson .core .JsonTokenId
21- import com .fasterxml .jackson .core .Version
22- import com .fasterxml .jackson .core .json .JsonWriteFeature
23- import com .fasterxml .jackson .core .util .DefaultPrettyPrinter
24-
25- import com .fasterxml .jackson .databind .Module .SetupContext
26- import com .fasterxml .jackson .databind ._
27- import com .fasterxml .jackson .databind .`type` .TypeFactory
28- import com .fasterxml .jackson .databind .deser .Deserializers
29- import com .fasterxml .jackson .databind .json .JsonMapper
30- import com .fasterxml .jackson .databind .module .SimpleModule
31- import com .fasterxml .jackson .databind .ser .Serializers
32- import com .fasterxml .jackson .databind .util .TokenBuffer
33- import com .fasterxml .jackson .datatype .jdk8 .Jdk8Module
34- import com .fasterxml .jackson .datatype .jsr310 .JavaTimeModule
35- import com .fasterxml .jackson .module .paramnames .ParameterNamesModule
36- import com .fasterxml .jackson .module .scala .DefaultScalaModule
17+ import com .fasterxml .jackson .annotation .JsonFormat
18+ import tools .jackson .core .{ JsonGenerator , JsonParser , JsonTokenId , Version }
19+ import tools .jackson .core .json .{ JsonFactory , JsonWriteFeature }
20+ import tools .jackson .databind .JacksonModule .SetupContext
21+ import tools .jackson .databind ._
22+ import tools .jackson .databind .`type` .TypeFactory
23+ import tools .jackson .databind .cfg .DateTimeFeature
24+ import tools .jackson .databind .deser .Deserializers
25+ import tools .jackson .databind .json .JsonMapper
26+ import tools .jackson .databind .module .SimpleModule
27+ import tools .jackson .databind .ser .Serializers
28+ import tools .jackson .databind .util .TokenBuffer
29+ import tools .jackson .module .scala .DefaultScalaModule
3730
3831import play .api .libs .json ._
3932
@@ -66,7 +59,7 @@ sealed class PlayJsonMapperModule(jsonConfig: JsonConfig) extends SimpleModule("
6659
6760// -- Serializers.
6861
69- private [jackson] class JsValueSerializer (jsonConfig : JsonConfig ) extends JsonSerializer [JsValue ] {
62+ private [jackson] class JsValueSerializer (jsonConfig : JsonConfig ) extends ValueSerializer [JsValue ] {
7063 import java .math .{ BigDecimal => JBigDec }
7164
7265 private def stripTrailingZeros (bigDec : JBigDec ): JBigDec = {
@@ -79,7 +72,7 @@ private[jackson] class JsValueSerializer(jsonConfig: JsonConfig) extends JsonSer
7972 }
8073 }
8174
82- override def serialize (value : JsValue , json : JsonGenerator , provider : SerializerProvider ): Unit = {
75+ override def serialize (value : JsValue , json : JsonGenerator , ctxt : SerializationContext ): Unit = {
8376 value match {
8477 case JsNumber (v) => {
8578 // Workaround #3784: Same behaviour as if JsonGenerator were
@@ -89,18 +82,22 @@ private[jackson] class JsValueSerializer(jsonConfig: JsonConfig) extends JsonSer
8982 val va = v.abs
9083 va <= jsonConfig.bigDecimalSerializerConfig.maxPlain && va >= jsonConfig.bigDecimalSerializerConfig.minPlain
9184 }
92- val stripped = stripTrailingZeros(v.bigDecimal)
93- val raw = if (shouldWritePlain) stripped.toPlainString else stripped.toString
94-
95- if (raw.exists(c => c == 'E' || c == '.' ))
96- json.writeNumber(raw)
97- else
98- json match {
99- case tb : TokenBuffer =>
100- tb.writeNumber(raw, true )
101- case _ =>
102- json.writeNumber(raw)
103- }
85+ val stripped = stripTrailingZeros(v.bigDecimal)
86+ val (raw, rawAsBigDecimal) = if (shouldWritePlain) {
87+ val str = stripped.toPlainString
88+ (str, new JBigDec (str))
89+ } else {
90+ (stripped.toString, stripped)
91+ }
92+
93+ json match {
94+ case tb : TokenBuffer =>
95+ // If the JsonGenerator is a TokenBuffer, use its writeNumber specific method
96+ val isInteger = raw.forall(c => c != 'E' && c != '.' )
97+ tb.writeNumber(raw, isInteger)
98+ case _ =>
99+ json.writeNumber(rawAsBigDecimal)
100+ }
104101 }
105102
106103 case JsString (v) => json.writeString(v)
@@ -109,16 +106,16 @@ private[jackson] class JsValueSerializer(jsonConfig: JsonConfig) extends JsonSer
109106 case JsArray (elements) => {
110107 json.writeStartArray()
111108 elements.foreach { t =>
112- serialize(t, json, provider )
109+ serialize(t, json, ctxt )
113110 }
114111 json.writeEndArray()
115112 }
116113
117114 case JsObject (values) => {
118115 json.writeStartObject()
119116 values.foreach { t =>
120- json.writeFieldName (t._1)
121- serialize(t._2, json, provider )
117+ json.writeName (t._1)
118+ serialize(t._2, json, ctxt )
122119 }
123120 json.writeEndObject()
124121 }
@@ -152,7 +149,7 @@ private[jackson] case class ReadingMap(content: ListBuffer[(String, JsValue)]) e
152149}
153150
154151private [jackson] class JsValueDeserializer (factory : TypeFactory , klass : Class [? ], jsonConfig : JsonConfig )
155- extends JsonDeserializer [Object ] {
152+ extends ValueDeserializer [Object ] {
156153 override def isCachable : Boolean = true
157154
158155 override def deserialize (jp : JsonParser , ctxt : DeserializationContext ): JsValue = {
@@ -168,7 +165,7 @@ private[jackson] class JsValueDeserializer(factory: TypeFactory, klass: Class[?]
168165 jp : JsonParser ,
169166 parserContext : List [DeserializerContext ]
170167 ): (Some [JsNumber ], List [DeserializerContext ]) = {
171- BigDecimalParser .parse(jp.getText , jsonConfig) match {
168+ BigDecimalParser .parse(jp.getString , jsonConfig) match {
172169 case JsSuccess (bigDecimal, _) =>
173170 (Some (JsNumber (bigDecimal)), parserContext)
174171
@@ -193,14 +190,14 @@ private[jackson] class JsValueDeserializer(factory: TypeFactory, klass: Class[?]
193190 ctxt : DeserializationContext ,
194191 parserContext : List [DeserializerContext ]
195192 ): JsValue = {
196- if (jp.getCurrentToken == null ) {
193+ if (jp.currentToken() == null ) {
197194 jp.nextToken() // happens when using treeToValue (we're not parsing tokens)
198195 }
199196
200- val valueAndCtx = (jp.getCurrentToken .id(): @ switch) match {
197+ val valueAndCtx = (jp.currentToken() .id(): @ switch) match {
201198 case JsonTokenId .ID_NUMBER_INT | JsonTokenId .ID_NUMBER_FLOAT => parseBigDecimal(jp, parserContext)
202199
203- case JsonTokenId .ID_STRING => (Some (JsString (jp.getText )), parserContext)
200+ case JsonTokenId .ID_STRING => (Some (JsString (jp.getString )), parserContext)
204201
205202 case JsonTokenId .ID_TRUE => (Some (JsBoolean (true )), parserContext)
206203
@@ -218,7 +215,7 @@ private[jackson] class JsValueDeserializer(factory: TypeFactory, klass: Class[?]
218215
219216 case JsonTokenId .ID_START_OBJECT => (None , ReadingMap (ListBuffer ()) +: parserContext)
220217
221- case JsonTokenId .ID_FIELD_NAME =>
218+ case JsonTokenId .ID_PROPERTY_NAME =>
222219 parserContext match {
223220 case (c : ReadingMap ) :: stack => (None , c.setField(jp.currentName()) +: stack)
224221 case _ => throw new RuntimeException (" We should be reading map, something got wrong" )
@@ -248,26 +245,39 @@ private[jackson] class JsValueDeserializer(factory: TypeFactory, klass: Class[?]
248245 }
249246
250247 // This is used when the root object is null, ie when deserializing "null"
251- override val getNullValue = JsNull
248+ override def getNullValue ( ctxt : DeserializationContext ) = JsNull
252249}
253250
254251private [jackson] class PlayDeserializers (jsonSettings : JsonConfig ) extends Deserializers .Base {
255- override def findBeanDeserializer (javaType : JavaType , config : DeserializationConfig , beanDesc : BeanDescription ) = {
252+ override def findBeanDeserializer (
253+ javaType : JavaType ,
254+ config : DeserializationConfig ,
255+ beanDescRef : BeanDescription .Supplier
256+ ) = {
256257 val klass = javaType.getRawClass
257258 if (classOf [JsValue ].isAssignableFrom(klass) || klass == JsNull .getClass) {
258259 new JsValueDeserializer (config.getTypeFactory, klass, jsonSettings)
259260 } else null
260261 }
262+
263+ override def hasDeserializerFor (config : DeserializationConfig , valueType : Class [? ]): Boolean = {
264+ classOf [JsValue ].isAssignableFrom(valueType) || valueType == JsNull .getClass
265+ }
261266}
262267
263268private [jackson] class PlaySerializers (jsonSettings : JsonConfig ) extends Serializers .Base {
264- override def findSerializer (config : SerializationConfig , javaType : JavaType , beanDesc : BeanDescription ) = {
265- val ser : Object = if (classOf [JsValue ].isAssignableFrom(beanDesc.getBeanClass)) {
269+ override def findSerializer (
270+ config : SerializationConfig ,
271+ javaType : JavaType ,
272+ beanDescRef : BeanDescription .Supplier ,
273+ formatOverrides : JsonFormat .Value
274+ ) = {
275+ val ser : Object = if (classOf [JsValue ].isAssignableFrom(beanDescRef.getBeanClass)) {
266276 new JsValueSerializer (jsonSettings)
267277 } else {
268278 null
269279 }
270- ser.asInstanceOf [JsonSerializer [Object ]]
280+ ser.asInstanceOf [ValueSerializer [Object ]]
271281 }
272282}
273283
@@ -283,51 +293,43 @@ private[play] object JacksonJson {
283293}
284294
285295private [play] case class JacksonJson (defaultMapperJsonConfig : JsonConfig ) {
286- private var currentMapper : ObjectMapper = null
287- private val defaultMapper : ObjectMapper = JsonMapper
296+ private var currentMapper : JsonMapper = null
297+ private val defaultMapper : JsonMapper = JsonMapper
288298 .builder(
289- new JsonFactoryBuilder ()
299+ JsonFactory
300+ .builder()
290301 .streamReadConstraints(defaultMapperJsonConfig.streamReadConstraints)
291302 .streamWriteConstraints(defaultMapperJsonConfig.streamWriteConstraints)
292303 .build()
293304 )
294305 .addModules(
295- new ParameterNamesModule (),
296- new Jdk8Module (),
297- new JavaTimeModule (),
298306 new DefaultScalaModule (),
299307 new PlayJsonMapperModule (defaultMapperJsonConfig),
300308 )
301309 .disable(DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES )
302- .disable(SerializationFeature .WRITE_DATES_AS_TIMESTAMPS )
303- .disable(SerializationFeature .WRITE_DURATIONS_AS_TIMESTAMPS )
310+ .disable(DateTimeFeature .WRITE_DATES_AS_TIMESTAMPS )
311+ .disable(DateTimeFeature .WRITE_DURATIONS_AS_TIMESTAMPS )
304312 .disable(SerializationFeature .FAIL_ON_EMPTY_BEANS )
305313 .build()
306314
307- private [play] def mapper (): ObjectMapper = if (currentMapper == null ) {
315+ private [play] def mapper (): JsonMapper = if (currentMapper == null ) {
308316 defaultMapper
309317 } else {
310318 currentMapper
311319 }
312320
313- private [play] def setObjectMapper (mapper : ObjectMapper ): Unit = {
321+ private [play] def setObjectMapper (mapper : JsonMapper ): Unit = {
314322 this .currentMapper = mapper
315323 }
316324
317- private def stringJsonGenerator (out : StringWriter ) =
318- mapper().getFactory.createGenerator(out)
319-
320- private def stringJsonGenerator (out : OutputStream ) =
321- mapper().getFactory.createGenerator(out)
322-
323325 def parseJsValue (data : Array [Byte ]): JsValue =
324- mapper().readValue(mapper().getFactory. createParser(data), classOf [JsValue ])
326+ mapper().readValue(mapper().createParser(data), classOf [JsValue ])
325327
326328 def parseJsValue (input : String ): JsValue =
327- mapper().readValue(mapper().getFactory. createParser(input), classOf [JsValue ])
329+ mapper().readValue(mapper().createParser(input), classOf [JsValue ])
328330
329331 def parseJsValue (stream : InputStream ): JsValue =
330- mapper().readValue(mapper().getFactory. createParser(stream), classOf [JsValue ])
332+ mapper().readValue(mapper().createParser(stream), classOf [JsValue ])
331333
332334 private def withStringWriter [T ](f : StringWriter => T ): T = {
333335 val sw = new StringWriter ()
@@ -347,35 +349,29 @@ private[play] case class JacksonJson(defaultMapperJsonConfig: JsonConfig) {
347349
348350 def generateFromJsValue (jsValue : JsValue , escapeNonASCII : Boolean ): String =
349351 withStringWriter { sw =>
350- val gen = stringJsonGenerator(sw)
351-
352- if (escapeNonASCII) {
353- gen.enable( JsonWriteFeature . ESCAPE_NON_ASCII .mappedFeature )
352+ val mapperWithEscapeNonASCII = if (escapeNonASCII) {
353+ mapper().rebuild().enable( JsonWriteFeature . ESCAPE_NON_ASCII ).build()
354+ } else {
355+ mapper( )
354356 }
355357
356- mapper() .writeValue(gen , jsValue)
358+ mapperWithEscapeNonASCII .writeValue(sw , jsValue)
357359 sw.flush()
358360 sw.getBuffer.toString
359361 }
360362
361363 def prettyPrint (jsValue : JsValue ): String = withStringWriter { sw =>
362- val gen = stringJsonGenerator(sw).setPrettyPrinter(
363- new DefaultPrettyPrinter ()
364- )
365364 val writer : ObjectWriter = mapper().writerWithDefaultPrettyPrinter()
366365
367- writer.writeValue(gen , jsValue)
366+ writer.writeValue(sw , jsValue)
368367 sw.flush()
369368 sw.getBuffer.toString
370369 }
371370
372371 def prettyPrintToStream (jsValue : JsValue , stream : OutputStream ): Unit = {
373- val gen = stringJsonGenerator(stream).setPrettyPrinter(
374- new DefaultPrettyPrinter ()
375- )
376372 val writer : ObjectWriter = mapper().writerWithDefaultPrettyPrinter()
377373
378- writer.writeValue(gen , jsValue)
374+ writer.writeValue(stream , jsValue)
379375 }
380376
381377 def jsValueToBytes (jsValue : JsValue ): Array [Byte ] =
0 commit comments