All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dslplatform.api.client.JsonSerialization.scala Maven / Gradle / Ivy

package com.dslplatform.api.client

import scala.io.Source
import scala.reflect.ClassTag
import scala.xml.Elem
import scala.xml.parsing.ConstructingParser
import org.joda.time.DateTime
import org.joda.time.LocalDate
import org.joda.time.format.DateTimeFormat
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.Version
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.InjectableValues
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
import com.dslplatform.api.patterns.ServiceLocator
import com.fasterxml.jackson.databind.JavaType
import com.fasterxml.jackson.module.scala.ser.CustomDefaultScalaModule
import com.fasterxml.jackson.databind.SerializationConfig
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.MapperFeature

class JsonSerialization(locator: ServiceLocator) {

  // ---- Date -------------------------------------------------------------------

  private val dateFormat = DateTimeFormat.forPattern("y-MM-dd'T00:00:00")

  private val dateSerializer = new JsonSerializer[LocalDate] {
    override def serialize(value: LocalDate, generator: JsonGenerator, x: SerializerProvider) =
      generator.writeString(dateFormat.print(value))
  }

  private val dateDeserializer = new JsonDeserializer[LocalDate] {
    override def deserialize(parser: JsonParser, context: DeserializationContext) =
      dateFormat.parseLocalDate(parser.getValueAsString())
  }

  // ---- TimeStamp --------------------------------------------------------------

  private val timestampSerializer = new JsonSerializer[DateTime] {
    override def serialize(value: DateTime, generator: JsonGenerator, x: SerializerProvider) =
      generator.writeString(value.toString())
  }

  private val timestampDeserializer = new JsonDeserializer[DateTime] {
    override def deserialize(parser: JsonParser, context: DeserializationContext) =
      new DateTime(parser.getValueAsString())
  }

  // ---- BigDecimal-------------------------------------------------------------------------

  private val bigDecimalSerializer = new JsonSerializer[BigDecimal] {
    override def serialize(value: BigDecimal, generator: JsonGenerator, x: SerializerProvider) =
      generator.writeString(value.toString)
  }

  private val bigDecimalDeserializer = new JsonDeserializer[BigDecimal] {
    override def deserialize(parser: JsonParser, context: DeserializationContext) =
      BigDecimal(parser.getValueAsString())
  }

  // ---- Elem -------------------------------------------------------------------

  private val elemSerializer = new JsonSerializer[Elem] {
    override def serialize(value: Elem, generator: JsonGenerator, x: SerializerProvider) =
      generator.writeString(value.toString())
  }

  private val elemDeserializer = new JsonDeserializer[Elem] {
    override def deserialize(parser: JsonParser, context: DeserializationContext) =
      ConstructingParser
        .fromSource(Source.fromString(parser.getValueAsString()), true)
        .document.docElem.asInstanceOf[Elem]
  }

  // ----serializationModule -----------------------------------------------------

  private val version = new Version(0, 0, 0, "SNAPSHOT", "com.dslplatform", "dsl-client-scala")

  private val serializationModule =
    new SimpleModule("SerializationModule", version)
      .addSerializer(classOf[LocalDate], dateSerializer)
      .addSerializer(classOf[DateTime], timestampSerializer)
      .addSerializer(classOf[BigDecimal], bigDecimalSerializer)
      .addSerializer(classOf[Elem], elemSerializer)

  private val serializationMapper =
    new ObjectMapper()
      .registerModule(CustomDefaultScalaModule)
      //.registerModule(DefaultScalaModule)
      .setSerializationInclusion(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL)
      .registerModule(serializationModule)
      //.configure(MapperFeature.AUTO_DETECT_GETTERS, false)
      //.configure(MapperFeature.AUTO_DETECT_FIELDS, false)
      //.configure(MapperFeature.AUTO_DETECT_IS_GETTERS, false)
      //.configure(MapperFeature.AUTO_DETECT_SETTERS, false)

  // ----deserializationModule----------------------------------------------------

  private val deserializationModule =
    new SimpleModule("DeserializationModule", version)
      .addDeserializer(classOf[LocalDate], dateDeserializer)
      .addDeserializer(classOf[DateTime], timestampDeserializer)
      .addDeserializer(classOf[BigDecimal], bigDecimalDeserializer)
      .addDeserializer(classOf[Elem], elemDeserializer)

  private val deserializationMapper = {
    val mapper = new ObjectMapper()
    mapper.registerModule(DefaultScalaModule)
      .registerModule(deserializationModule)
      .setInjectableValues(new InjectableValues.Std addValue ("__locator", locator))
      .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
  }

  private val typeFactory = deserializationMapper.getTypeFactory()

  // -----------------------------------------------------------------------

  def serialize[T](data: T): String = serializationMapper.writeValueAsString(data)

  private def getClassTag[T: ClassTag]: ClassTag[T] = implicitly[ClassTag[T]]

  def deserialize[TResult: ClassTag](data: Array[Byte]): TResult =
    deserializationMapper.readValue[TResult](data, getClassTag[TResult].runtimeClass.asInstanceOf[Class[TResult]])

  def deserialize[TResult](data: Array[Byte], buildType: JavaType): TResult =
    deserializationMapper.readValue(data, buildType)

  def deserializeList[TResult: ClassTag](data: Array[Byte]): IndexedSeq[TResult] =
    deserializationMapper.readValue(data, buildCollectionType[TResult])

  def deserializeList[TResult](clazz: Class[_], data: Array[Byte]): IndexedSeq[TResult] =
    deserializationMapper.readValue(data, buildCollectionType(clazz))

  private def buildCollectionType[TResult: ClassTag] =
    typeFactory.constructCollectionLikeType(classOf[IndexedSeq[_]],
      getClassTag[TResult].runtimeClass.asInstanceOf[Class[TResult]])

  private def buildCollectionType(clazz: Class[_]) =
    typeFactory.constructCollectionLikeType(classOf[IndexedSeq[_]], clazz)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy