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

com.wavesplatform.api.http.CustomJson.scala Maven / Gradle / Ivy

The newest version!
package com.wavesplatform.api.http

import java.io.IOException
import akka.http.scaladsl.model.MediaTypes.`application/json`
import akka.http.scaladsl.model.{MediaRange, MediaType}
import com.fasterxml.jackson.core.io.SegmentedStringWriter
import com.fasterxml.jackson.core.util.BufferRecyclers
import com.fasterxml.jackson.core.{JsonGenerator, JsonProcessingException}
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.databind.{JsonMappingException, JsonSerializer, ObjectMapper, SerializerProvider}
import com.wavesplatform.api.http.CustomJson.fieldNamesToTranslate
import play.api.libs.json.*

object NumberAsStringSerializer extends JsonSerializer[JsValue] {
  override def serialize(value: JsValue, json: JsonGenerator, provider: SerializerProvider): Unit =
    serializeWithNumberAsStrings(value, json, provider, insideStringifiedField = false)

  private def serializeWithNumberAsStrings(value: JsValue, json: JsonGenerator, provider: SerializerProvider, insideStringifiedField: Boolean): Unit =
    value match {
      case JsNumber(v) if insideStringifiedField => json.writeString(v.bigDecimal.toPlainString)
      case JsNumber(v) => json.writeNumber(v.bigDecimal)
      case JsString(v) => json.writeString(v)
      case v: JsBoolean => json.writeBoolean(v.value)

      case JsArray(elements) =>
        json.writeStartArray()
        elements.foreach { t =>
          serializeWithNumberAsStrings(t, json, provider, insideStringifiedField)
        }
        json.writeEndArray()

      case JsObject(values) =>
        json.writeStartObject()
        values.foreach {
          case (name, JsNumber(v)) if fieldNamesToTranslate(name) =>
            json.writeStringField(name, v.bigDecimal.toPlainString)
          case (name, jsv) if fieldNamesToTranslate(name) =>
            json.writeFieldName(name)
            serializeWithNumberAsStrings(jsv, json, provider, insideStringifiedField = true)
          case (name, jsv) =>
            json.writeFieldName(name)
            serializeWithNumberAsStrings(jsv, json, provider, insideStringifiedField)
        }
        json.writeEndObject()

      case JsNull => json.writeNull()
    }
}

object CustomJson {
  val jsonWithNumbersAsStrings: MediaType.WithFixedCharset = `application/json`.withParams(Map("large-significand-format" -> "string"))

  val fieldNamesToTranslate = Set(
    "amount",
    "available",
    "balance",
    "buyMatcherFee",
    "currentReward",
    "desiredReward",
    "effective",
    "fee",
    "feeAmount",
    "generating",
    "in",
    "matcherFee",
    "minIncrement",
    "minSponsoredAssetFee",
    "out",
    "price",
    "quantity",
    "regular",
    "reward",
    "rewardShares",
    "sellMatcherFee",
    "sponsorBalance",
    "totalAmount",
    "totalFee",
    "totalWavesAmount",
    "value"
  )

  def acceptsNumbersAsStrings(mr: MediaRange): Boolean = mr match {
    case MediaRange.One(`jsonWithNumbersAsStrings`, _) => true
    case _                                             => false
  }

  private lazy val mapper = (new ObjectMapper)
    .registerModule(new SimpleModule("WavesJson").addSerializer(classOf[JsValue], NumberAsStringSerializer))
    .configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true)

  def writeValueAsString(value: JsValue): String = {
    val sw = new SegmentedStringWriter(BufferRecyclers.getBufferRecycler)
    try mapper.writeValue(sw, value)
    catch {
      case e: JsonProcessingException =>
        throw e
      case e: IOException =>
        // shouldn't really happen, but is declared as possibility so:
        throw JsonMappingException.fromUnexpectedIOE(e)
    }
    sw.getAndClear
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy