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

com.dslplatform.json.runtime.ScalaMapEncoder.scala Maven / Gradle / Ivy

The newest version!
package com.dslplatform.json
package runtime

final class ScalaMapEncoder[K, V](
  json: DslJson[_],
  checkForConversionToString: Boolean,
  keyEncoder: Option[JsonWriter.WriteObject[K]],
  valueEncoder: Option[JsonWriter.WriteObject[V]]
) extends JsonWriter.WriteObject[scala.collection.Map[K, V]] {
  require(json ne null, "json can't be null")
  require(keyEncoder ne null, "keyEncoder can't be null")
  require(valueEncoder ne null, "valueEncoder can't be null")

  private val EMPTY = Array[Byte]('{', '}')

  override def write(writer: JsonWriter, value: scala.collection.Map[K, V]): Unit = {
    if (value.isEmpty) writer.writeAscii(EMPTY)
    else if (keyEncoder.isDefined && valueEncoder.isDefined) {
      val ke = keyEncoder.get
      val ve = valueEncoder.get
      writer.writeByte(JsonWriter.OBJECT_START)
      val iter = value.iterator
      val (k1, v1) = iter.next()
      if (checkForConversionToString) writeQuoted(writer, ke, k1)
      else ke.write(writer, k1)
      writer.writeByte(JsonWriter.SEMI)
      ve.write(writer, v1)
      while (iter.hasNext) {
        val (k, v) = iter.next()
        writer.writeByte(JsonWriter.COMMA)
        if (checkForConversionToString) writeQuoted(writer, ke, k)
        else ke.write(writer, k)
        writer.writeByte(JsonWriter.SEMI)
        ve.write(writer, v)
      }
      writer.writeByte(JsonWriter.OBJECT_END)
    } else {
      var pastFirst = false
      writer.writeByte(JsonWriter.OBJECT_START)
      var lastKeyClass: Option[Class[_]] = None
      var lastValueClass: Option[Class[_]] = None
      var lastKeyEncoder = keyEncoder
      var lastValueEncoder: Option[JsonWriter.WriteObject[V]] = None
      val iter = value.iterator
      while (iter.hasNext) {
        val (k, v) = iter.next()
        if (pastFirst) writer.writeByte(JsonWriter.COMMA)
        else pastFirst = true
        val currentKeyClass = k.getClass
        if (keyEncoder.isEmpty && !lastKeyClass.contains(currentKeyClass)) {
          lastKeyClass = Some(currentKeyClass)
          json.tryFindWriter(currentKeyClass) match {
            case wo: JsonWriter.WriteObject[K] => lastKeyEncoder = Some(wo)
            case _ => throw new ConfigurationException(s"Unable to find writer for $lastKeyClass")
          }
        }
        writeQuoted(writer, lastKeyEncoder.get, k)
        writer.writeByte(JsonWriter.SEMI)
        if (valueEncoder.isDefined) valueEncoder.get.write(writer, v)
        else if (v == null || v == None) writer.writeNull()
        else {
          val currentValueClass = v.getClass
          if (!lastValueClass.contains(currentValueClass)) {
            lastValueClass = Some(currentValueClass)
            json.tryFindWriter(currentValueClass) match {
              case wo: JsonWriter.WriteObject[V] => lastValueEncoder = Some(wo)
              case _ => throw new ConfigurationException(s"Unable to find writer for $lastValueClass")
            }
          }
          lastValueEncoder.get.write(writer, v)
        }
      }
      writer.writeByte(JsonWriter.OBJECT_END)
    }
  }

  private def writeDouble(value: Double, writer: JsonWriter): Unit = {
    if (value == Double.NaN) writer.writeAscii("NaN")
    else if (value == Double.PositiveInfinity) writer.writeAscii("Infinity")
    else if (value == Double.NegativeInfinity) writer.writeAscii("-Infinity")
    else {
      writer.writeByte(JsonWriter.QUOTE)
      NumberConverter.serialize(value, writer)
      writer.writeByte(JsonWriter.QUOTE)
    }
  }

  private def writeFloat(value: Float, writer: JsonWriter): Unit = {
    if (value == Float.NaN) writer.writeAscii("NaN")
    else if (value == Float.PositiveInfinity) writer.writeAscii("Infinity")
    else if (value == Float.NegativeInfinity) writer.writeAscii("-Infinity")
    else {
      writer.writeByte(JsonWriter.QUOTE)
      NumberConverter.serialize(value, writer)
      writer.writeByte(JsonWriter.QUOTE)
    }
  }

  private def writeQuoted(writer: JsonWriter, keyWriter: JsonWriter.WriteObject[K], key: K): Unit = {
    key match {
      case k: Double => writeDouble(k, writer)
      case k: java.lang.Double => writeDouble(k, writer)
      case k: Float => writeFloat(k, writer)
      case k: java.lang.Float => writeFloat(k, writer)
      case _: Number =>
        writer.writeByte(JsonWriter.QUOTE)
        keyWriter.write(writer, key)
        writer.writeByte(JsonWriter.QUOTE)
      case _ =>
        keyWriter.write(writer, key)
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy