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

play.api.libs.json.KeyReads.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. 
 */

package play.api.libs.json

import scala.util.control.NonFatal

/**
 * Used to read object key for types other than `String`.
 *
 * @see [[Reads.keyMapReads]]
 */
trait KeyReads[T] { self =>
  def readKey(key: String): JsResult[T]

  final def map[U](f: T => U): KeyReads[U] = KeyReads[U] { key =>
    self.readKey(key).map(f)
  }
}

object KeyReads extends EnvKeyReads with LowPriorityKeyReads {

  /**
   * Returns an instance which uses `f` as [[KeyReads.readKey]] function.
   */
  def apply[T](f: String => JsResult[T]): KeyReads[T] = new KeyReads[T] {
    def readKey(key: String) = f(key)
  }

  implicit val charKeyReads: KeyReads[Char] = KeyReads[Char] {
    _.headOption match {
      case Some(ch) => JsSuccess(ch)
      case _        => JsError("error.expected.character")
    }
  }

  implicit val booleanKeyReads: KeyReads[Boolean] = KeyReads[Boolean] {
    case "true"  => JsSuccess(true)
    case "false" => JsSuccess(false)
    case _       => JsError("error.expected.boolean")
  }

  implicit val byteKeyReads: KeyReads[Byte] = charKeyReads.map(_.toByte)

  implicit val shortKeyReads: KeyReads[Short] =
    unsafe[Short]("error.expected.short")(_.toShort)

  implicit val intKeyReads: KeyReads[Int] =
    unsafe[Int]("error.expected.int")(_.toInt)

  implicit val longKeyReads: KeyReads[Long] =
    unsafe[Long]("error.expected.long")(_.toLong)

  implicit val floatKeyReads: KeyReads[Float] =
    unsafe[Float]("error.expected.float")(_.toFloat)

  implicit val doubleKeyReads: KeyReads[Double] =
    unsafe[Double]("error.expected.double")(_.toDouble)

  private def unsafe[T](err: String)(f: String => T): KeyReads[T] =
    KeyReads[T] { key =>
      try {
        JsSuccess(f(key))
      } catch {
        case NonFatal(_) => JsError(err)
      }
    }
}

private[json] sealed trait LowPriorityKeyReads {
  implicit def readableKeyReads[T](implicit r: Reads[T]): KeyReads[T] =
    KeyReads[T] { key =>
      r.reads(JsString(key))
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy