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

org.json4sbt.Extraction.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2009-2010 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.json4sbt

import java.lang.{Integer => JavaInteger, Long => JavaLong, Short => JavaShort, Byte => JavaByte, Boolean => JavaBoolean, Double => JavaDouble, Float => JavaFloat}
import java.math.{BigDecimal => JavaBigDecimal}
import java.util.Date
import java.sql.Timestamp
import reflect._
import scala.reflect.Manifest
import scala.collection.JavaConverters._

/** Function to extract values from JSON AST using case classes.
 *
 *  See: ExtractionExamples.scala
 */
object Extraction {

  /** Extract a case class from JSON.
   * @see org.json4sbt.JsonAST.JValue#extract
   * @throws MappingException is thrown if extraction fails
   */
  def extract[A](json: JValue)(implicit formats: Formats, mf: Manifest[A]): A = {
    try {
      extract(json, Reflector.scalaTypeOf[A]).asInstanceOf[A]
    } catch {
      case e: MappingException => throw e
      case e: Exception =>
        throw new MappingException("unknown error", e)
    }
  }

  /** Extract a case class from JSON.
   * @see org.json4sbt.JsonAST.JValue#extract
   */
  def extractOpt[A](json: JValue)(implicit formats: Formats, mf: Manifest[A]): Option[A] =
    try { Option(extract(json)(formats, mf)) } catch { case _: MappingException => None }

  def extract(json: JValue, target: TypeInfo)(implicit formats: Formats): Any = extract(json, ScalaType(target))

  /** Decompose a case class into JSON.
   * 

* Example:

   * case class Person(name: String, age: Int)
   * implicit val formats = org.json4sbt.DefaultFormats
   * Extraction.decompose(Person("joe", 25)) == JObject(JField("age",JInt(25)) :: JField("name",JString("joe")) :: Nil)
   * 
*/ def decomposeWithBuilder[T](a: Any, builder: JsonWriter[T])(implicit formats: Formats): T = { internalDecomposeWithBuilder(a,builder)(formats) builder.result } /** Load lazy val value * * This is a fix for failed lazy val serialization from FieldSerializer (see org.json4sbt.native.LazyValBugs test). * * We do this by finding the hidden lazy method which will have same name as the lazy val name * but with suffix "$lzycompute" (for scala v2.10+), then invoke the method if found, and return the value. * * The "$lzycompute" method naming could be changed in future so this method must be adjusted if that happens. * * @param a Object to be serialized * @param name Field name to be checked * @param defaultValue Default value if lazy method is not found * @return Value of invoked lazy method if found, else return the default value */ def loadLazyValValue(a: Any, name: String, defaultValue: Any) = { try { val method = a.getClass.getDeclaredMethod(name + "$lzycompute") method.setAccessible(true) method.invoke(a) } catch { case e: Exception => defaultValue } } private[this] lazy val typesHaveNaN: Set[Class[_]] = Set( classOf[Double], classOf[Float], classOf[java.lang.Double], classOf[java.lang.Float] ) /** Decompose a case class into JSON. * * This is broken out to avoid calling builder.result when we return from recursion */ def internalDecomposeWithBuilder[T](a: Any, builder: JsonWriter[T])(implicit formats: Formats):Unit = { val current = builder def prependTypeHint(clazz: Class[_], o: JObject) = JObject(JField(formats.typeHintFieldName, JString(formats.typeHints.hintFor(clazz))) :: o.obj) def addField(name: String, v: Any, obj: JsonWriter[T]) = v match { case None => formats.emptyValueStrategy.noneValReplacement map (internalDecomposeWithBuilder(_, obj.startField(name))) case oth => internalDecomposeWithBuilder(v, obj.startField(name)) } val serializer = formats.typeHints.serialize val any = a.asInstanceOf[AnyRef] def decomposeObject(k: Class[_]) = { val klass = Reflector.scalaTypeOf(k) val descriptor = Reflector.describe(klass).asInstanceOf[reflect.ClassDescriptor] val ctorParams = descriptor.mostComprehensive.map(_.name) val iter = descriptor.properties.iterator val obj = current.startObject() if (formats.typeHints.containsHint(k)) { val f = obj.startField(formats.typeHintFieldName) f.string(formats.typeHints.hintFor(k)) } val fs = formats.fieldSerializer(k) while(iter.hasNext) { val prop = iter.next() val fieldVal = prop.get(any) val n = prop.name if (fs.isDefined) { val fieldSerializer = fs.get val ff = (fieldSerializer.serializer orElse Map((n, fieldVal) -> Some((n, fieldVal))))((n, fieldVal)) if (ff.isDefined) { val Some((nn, vv)) = ff val vvv = if (fieldSerializer.includeLazyVal) loadLazyValValue(a, nn, vv) else vv addField(nn, vvv, obj) } } else if (ctorParams contains prop.name) addField(n, fieldVal, obj) } obj.endObject() } if (formats.customSerializer(formats).isDefinedAt(a)) { current addJValue formats.customSerializer(formats)(a) } else if (!serializer.isDefinedAt(a)) { val k = if (any != null) any.getClass else null // A series of if branches because of performance reasons if (any == null) { current.addJValue(JNull) } else if (classOf[JValue].isAssignableFrom(k)) { current.addJValue(any.asInstanceOf[JValue]) } else if (typesHaveNaN.contains(any.getClass) && any.toString == "NaN") { current.addJValue(JNull) } else if (Reflector.isPrimitive(any.getClass)) { writePrimitive(any, current)(formats) } else if (classOf[scala.collection.Map[_, _]].isAssignableFrom(k)) { val obj = current.startObject() val iter = any.asInstanceOf[scala.collection.Map[_, _]].iterator while(iter.hasNext) { iter.next() match { case (k: String, v) => addField(k, v, obj) case (k: Symbol, v) => addField(k.name, v, obj) case (k: Int, v) => addField(k.toString, v, obj) case (k: Long, v) => addField(k.toString, v, obj) case (k: Date, v) => addField(formats.dateFormat.format(k), v, obj) case (k: JavaInteger, v) => addField(k.toString, v, obj) case (k: BigInt, v) => addField(k.toString, v, obj) case (k: JavaLong, v) => addField(k.toString, v, obj) case (k: Short, v) => addField(k.toString, v, obj) case (k: JavaShort, v) => addField(k.toString, v, obj) case (k, v) => { val customKeySerializer = formats.customKeySerializer(formats) if(customKeySerializer.isDefinedAt(k)) { addField(customKeySerializer(k), v, obj) } else { fail("Do not know how to serialize key of type " + k.getClass + ". " + "Consider implementing a CustomKeySerializer.") } } } } obj.endObject() } else if (classOf[Iterable[_]].isAssignableFrom(k)) { val arr = current.startArray() val iter = any.asInstanceOf[Iterable[_]].iterator while(iter.hasNext) { internalDecomposeWithBuilder(iter.next(), arr) } arr.endArray() } else if (classOf[java.util.Collection[_]].isAssignableFrom(k)) { val arr = current.startArray() val iter = any.asInstanceOf[java.util.Collection[_]].iterator while(iter.hasNext) { internalDecomposeWithBuilder(iter.next(), arr) } arr.endArray() } else if (k.isArray) { val arr = current.startArray() val iter = any.asInstanceOf[Array[_]].iterator while(iter.hasNext) { internalDecomposeWithBuilder(iter.next(), arr) } arr.endArray() } else if (classOf[Option[_]].isAssignableFrom(k)) { val v = any.asInstanceOf[Option[_]] if (v.isDefined) { internalDecomposeWithBuilder(v.get, current) } } else if (classOf[Either[_, _]].isAssignableFrom(k)) { val v = any.asInstanceOf[Either[_, _]] if (v.isLeft) { internalDecomposeWithBuilder(v.left.get, current) } else { internalDecomposeWithBuilder(v.right.get, current) } } else if (classOf[(_, _)].isAssignableFrom(k)) { any.asInstanceOf[(_, _)] match { case (k: String, v) => val obj = current.startObject() addField(k, v, obj) obj.endObject() case (k: Symbol, v) => val obj = current.startObject() addField(k.name, v, obj) obj.endObject() case _: (_, _) => decomposeObject(k) } } else { decomposeObject(k) } } else current addJValue prependTypeHint(any.getClass, serializer(any)) } /** Decompose a case class into JSON. *

* Example:

   * case class Person(name: String, age: Int)
   * implicit val formats = org.json4sbt.DefaultFormats
   * Extraction.decompose(Person("joe", 25)) == JObject(JField("age",JInt(25)) :: JField("name",JString("joe")) :: Nil)
   * 
*/ def decompose(a: Any)(implicit formats: Formats): JValue = decomposeWithBuilder(a, if (formats.wantsBigDecimal) JsonWriter.bigDecimalAst else JsonWriter.ast) private[this] def writePrimitive(a: Any, builder: JsonWriter[_])(implicit formats: Formats) = a match { case x: String => builder.string(x) case x: Int => builder.int(x) case x: Long => builder.long(x) case x: Double => builder.double(x) case x: Float => builder.float(x) case x: Byte => builder.byte(x) case x: BigInt => builder.bigInt(x) case x: BigDecimal => builder.bigDecimal(x) case x: Boolean => builder.boolean(x) case x: Short => builder.short(x) case x: java.lang.Integer => builder.int(x.intValue()) case x: java.lang.Long => builder.long(x.longValue()) case x: java.lang.Double => builder.double(x.doubleValue()) case x: java.lang.Float => builder.float(x.floatValue()) case x: java.lang.Byte => builder.byte(x.byteValue()) case x: java.lang.Boolean => builder.boolean(x.booleanValue()) case x: java.lang.Short => builder.short(x.shortValue()) case x: java.math.BigDecimal => builder.bigDecimal(x) case x: Date => builder.string(formats.dateFormat.format(x)) case x: Symbol => builder.string(x.name) case _ => sys.error("not a primitive " + a.asInstanceOf[AnyRef].getClass) } /** Flattens the JSON to a key/value map. */ def flatten(json: JValue)(implicit formats: Formats = DefaultFormats): Map[String, String] = { def escapePath(str: String) = str def flatten0(path: String, json: JValue): Map[String, String] = { json match { case JNothing | JNull => Map() case JString(s) => Map(path -> ("\"" + ParserUtil.quote(s) + "\"")) case JDouble(num) => Map(path -> num.toString) case JDecimal(num) => Map(path -> num.toString) case JLong(num) => Map(path -> num.toString) case JInt(num) => Map(path -> num.toString) case JBool(value) => Map(path -> value.toString) case JObject(obj) => obj.foldLeft(Map[String, String]()) { case (map, (name, value)) => map ++ flatten0(path + "." + escapePath(name), value) } case JArray(arr) => arr.length match { case 0 => Map(path -> "[]") case _ => arr.foldLeft((Map[String, String](), 0)) { (tuple, value) => (tuple._1 ++ flatten0(path + "[" + tuple._2 + "]", value), tuple._2 + 1) }._1 } } } flatten0("", json) } /** Unflattens a key/value map to a JSON object. */ def unflatten(map: Map[String, String], useBigDecimalForDouble: Boolean = false, useBigIntForLong: Boolean = true): JValue = { import scala.util.matching.Regex def extractValue(value: String): JValue = value.toLowerCase match { case "" => JNothing case "null" => JNull case "true" => JBool.True case "false" => JBool.False case "[]" => JArray(Nil) case x @ _ => if (value.charAt(0).isDigit) { if (value.indexOf('.') == -1) { if (useBigIntForLong) JInt(BigInt(value)) else JLong(value.toLong) } else { if (!useBigDecimalForDouble) JDouble(ParserUtil.parseDouble(value)) else JDecimal(BigDecimal(value)) } } else JString(ParserUtil.unquote(value.substring(1))) } def submap(prefix: String): Map[String, String] = map.withFilter(t => t._1.startsWith(prefix)).map( t => (t._1.substring(prefix.length), t._2) ) val ArrayProp = new Regex("""^(\.([^\.\[]+))\[(\d+)\].*$""") val ArrayElem = new Regex("""^(\[(\d+)\]).*$""") val OtherProp = new Regex("""^(\.([^\.\[]+)).*$""") val uniquePaths = map.keys.foldLeft[Set[String]](Set()) { (set, key) => key match { case ArrayProp(p, f, i) => set + p case OtherProp(p, f) => set + p case ArrayElem(p, i) => set + p case x @ _ => set + x } }.toList.sortWith(_ < _) // Sort is necessary to get array order right uniquePaths.foldLeft[JValue](JNothing) { (jvalue, key) => jvalue.merge(key match { case ArrayProp(p, f, i) => JObject(List(JField(f, unflatten(submap(key))))) case ArrayElem(p, i) => JArray(List(unflatten(submap(key)))) case OtherProp(p, f) => JObject(List(JField(f, unflatten(submap(key))))) case "" => extractValue(map(key)) }) } } def extract(json: JValue, scalaType: ScalaType)(implicit formats: Formats): Any = { if (scalaType.isEither) { import scala.util.control.Exception.allCatch (allCatch opt { Left(extract(json, scalaType.typeArgs(0))) } orElse (allCatch opt { Right(extract(json, scalaType.typeArgs(1))) })).getOrElse(fail("Expected value but got " + json)) } else if (scalaType.isOption) { customOrElse(scalaType, json)(_.toOption flatMap (j => Option(extract(j, scalaType.typeArgs.head)))) } else if (scalaType.isMap) { json match { case JObject(xs) => { val kta = scalaType.typeArgs(0) val ta = scalaType.typeArgs(1) Map(xs.map(x => (convert(x._1, kta, formats), extract(x._2, ta))): _*) } case x => fail("Expected object but got " + x) } } else if (scalaType.isCollection) { customOrElse(scalaType, json)(new CollectionBuilder(_, scalaType).result) } else if (classOf[(_, _)].isAssignableFrom(scalaType.erasure) && (classOf[String].isAssignableFrom(scalaType.typeArgs.head.erasure) || classOf[Symbol].isAssignableFrom(scalaType.typeArgs.head.erasure) )) { val ta = scalaType.typeArgs(1) json match { case JObject(xs :: Nil) => if (classOf[Symbol].isAssignableFrom(scalaType.typeArgs.head.erasure)) (Symbol(xs._1), extract(xs._2, ta)) else (xs._1, extract(xs._2, ta)) case x => fail("Expected object with 1 element but got " + x) } } else { Reflector.describe(scalaType) match { case PrimitiveDescriptor(tpe, default) => convert(json, tpe, formats, default) //customOrElse(tpe, json)(convert(_, tpe, formats, default)) case o : ClassDescriptor if o.erasure.isSingleton => if (json==JObject(List.empty)) o.erasure.singletonInstance.getOrElse(sys.error(s"Not a case object: ${o.erasure}")) else sys.error(s"Expected empty parameter list for singleton instance, got ${json} instead") case c: ClassDescriptor => new ClassInstanceBuilder(json, c).result } } } private class CollectionBuilder(json: JValue, tpe: ScalaType)(implicit formats: Formats) { private[this] val typeArg = tpe.typeArgs.head private[this] def mkCollection(constructor: Array[_] => Any) = { val array: Array[_] = json match { case JArray(arr) => arr.map(extract(_, typeArg)).toArray case JNothing | JNull => Array[AnyRef]() case x => fail("Expected collection but got " + x + " for root " + json + " and mapping " + tpe) } constructor(array) } private[this] def mkTypedArray(a: Array[_]) = { import java.lang.reflect.Array.{newInstance => newArray} a.foldLeft((newArray(typeArg.erasure, a.length), 0)) { (tuple, e) => { java.lang.reflect.Array.set(tuple._1, tuple._2, e) (tuple._1, tuple._2 + 1) }}._1 } def result: Any = { val custom = formats.customDeserializer(formats) if (custom.isDefinedAt(tpe.typeInfo, json)) custom(tpe.typeInfo, json) else if (tpe.erasure == classOf[List[_]]) mkCollection(a => List(a: _*)) else if (tpe.erasure == classOf[Set[_]]) mkCollection(a => Set(a: _*)) else if (tpe.erasure == classOf[scala.collection.mutable.Set[_]]) mkCollection(a => scala.collection.mutable.Set(a: _*)) else if (tpe.erasure == classOf[scala.collection.mutable.Seq[_]]) mkCollection(a => scala.collection.mutable.Seq(a: _*)) else if (tpe.erasure == classOf[java.util.ArrayList[_]]) mkCollection(a => new java.util.ArrayList[Any](a.toList.asJavaCollection)) else if (tpe.erasure.isArray) mkCollection(mkTypedArray) else if (classOf[scala.collection.generic.GenericTraversableTemplate[_, Any]].isAssignableFrom(tpe.erasure)) { reflect.ScalaSigReader.companions(tpe.erasure.getName) match { case Some(tuple) => // can't `case Some((_, Some(c)))` due to Scala 2.10 bug tuple match { case (_, Some(c)) => import language.reflectiveCalls val companion = c.asInstanceOf[{def apply(elems: Seq[_]): Any}] mkCollection(a => companion(a.toSeq)) case _ => fail("Expected collection but got " + tpe) } case _ => fail("Expected collection but got " + tpe) } } else fail("Expected collection but got " + tpe) } } private class ClassInstanceBuilder(json: JValue, descr: ClassDescriptor)(implicit formats: Formats) { private object TypeHint { def unapply(fs: List[JField]): Option[(String, List[JField])] = if (formats.typeHints == NoTypeHints) None else { fs.partition(_._1 == formats.typeHintFieldName) match { case (Nil, _) => None case (t, f) => Some((t.head._2.values.toString, f)) } } } private[this] var _constructor: ConstructorDescriptor = null private[this] def constructor = { if (_constructor == null) { _constructor = if (descr.constructors.size == 1) descr.constructors.head else { val argNames = json match { case JObject(fs) => fs.map(_._1) case _ => Nil } val r = descr.bestMatching(argNames) r.getOrElse(fail("No constructor for type " + descr.erasure + ", " + json)) } } _constructor } private[this] def setFields(a: AnyRef) = json match { case JObject(fields) => formats.fieldSerializer(a.getClass) map { serializer => val ctorArgs = constructor.params.map(_.name) val fieldsToSet = descr.properties.filterNot(f => ctorArgs.contains(f.name)) val idPf: PartialFunction[JField, JField] = { case f => f } val jsonSerializers = (fields map { f => val JField(n, v) = (serializer.deserializer orElse idPf)(f) (n, (n, v)) }).toMap fieldsToSet foreach { prop => jsonSerializers get prop.name foreach { case (_, v) => val vv = extract(v, prop.returnType) // If includeLazyVal is set, try to find and initialize lazy val. // This is to prevent the extracted value to be overwritten by the lazy val initialization. if (serializer.includeLazyVal) loadLazyValValue(a, prop.name, vv) else () prop.set(a, vv) } } } a case _ => a } private[this] def buildCtorArg(json: JValue, descr: ConstructorParamDescriptor) = { val default = descr.defaultValue def defv(v: Any) = if (default.isDefined) default.get() else v if (descr.isOptional && json == JNothing) defv(None) else { try { val x = if (json == JNothing && default.isDefined) default.get() else extract(json, descr.argType) if (descr.isOptional) { if (x == null) defv(None) else x } else if (x == null) { if(!default.isDefined && descr.argType <:< ScalaType(manifest[AnyVal])) { throw new MappingException("Null invalid value for a sub-type of AnyVal") } else { defv(x) } } else x } catch { case e @ MappingException(msg, _) => if (descr.isOptional && !formats.strictOptionParsing) defv(None) else fail("No usable value for " + descr.name + "\n" + msg, e) } } } private[this] def instantiate = { val jconstructor = constructor.constructor val deserializedJson = json match { case JObject(fields) => formats.fieldSerializer(descr.erasure.erasure) map { serializer => val idPf: PartialFunction[JField, JField] = { case f => f } JObject(fields map { f => (serializer.deserializer orElse idPf)(f) }) } getOrElse json case other: JValue => other } val args = constructor.params.map(a => buildCtorArg(deserializedJson \ a.name, a)) try { if (jconstructor.getDeclaringClass == classOf[java.lang.Object]) { deserializedJson match { case JObject(TypeHint(t, fs)) => mkWithTypeHint(t: String, fs: List[JField], descr.erasure) case v: JValue => v.values } } else { val instance = jconstructor.invoke(descr.companion, args) setFields(instance.asInstanceOf[AnyRef]) } } catch { case e @ (_:IllegalArgumentException | _:InstantiationException) => val argsTypeComparisonResult = { val constructorParamTypes = jconstructor.getParameterTypes().map(paramType => Some(paramType.asInstanceOf[Class[Any]])) val argTypes = args.map(arg => Some(if (arg != null) arg.getClass.asInstanceOf[Class[Any]] else null)) constructorParamTypes.zipAll(argTypes, None, None).map { case (None, Some(argType)) => s"REDUNDANT(${argType.getName})" case (Some(constructorParamType), None) => s"MISSING(${constructorParamType.getName})" case (Some(constructorParamType), Some(argType)) if argType == null || constructorParamType.isAssignableFrom(argType) => "MATCH" case (Some(constructorParamType), Some(argType)) => s"${argType.getName}(${argType.getClassLoader}) !<: ${constructorParamType.getName}(${constructorParamType.getClassLoader})" } } fail("Parsed JSON values do not match with class constructor\nargs=" + args.mkString(",") + "\narg types=" + args.map(a => if (a != null) a.asInstanceOf[AnyRef].getClass.getName else "null").mkString(",") + "\nexecutable=" + jconstructor + "\ncause=" + e.getMessage + "\ntypes comparison result=" + argsTypeComparisonResult.mkString(",")) } } private[this] def mkWithTypeHint(typeHint: String, fields: List[JField], typeInfo: ScalaType) = { val obj = JObject(fields filterNot (_._1 == formats.typeHintFieldName)) val deserializer = formats.typeHints.deserialize if (!deserializer.isDefinedAt(typeHint, obj)) { val concreteClass = formats.typeHints.classFor(typeHint) getOrElse fail("Do not know how to deserialize '" + typeHint + "'") extract(obj, typeInfo.copy(erasure = concreteClass)) } else deserializer(typeHint, obj) } def result: Any = customOrElse(descr.erasure, json){ case JNull if formats.allowNull => null case JNull if !formats.allowNull => fail("Did not find value which can be converted into " + descr.fullName) case JObject(TypeHint(t, fs)) => mkWithTypeHint(t, fs, descr.erasure) case _ => instantiate } } private[this] def customOrElse(target: ScalaType, json: JValue)(thunk: JValue => Any)(implicit formats: Formats): Any = { val custom = formats.customDeserializer(formats) val targetType = target.typeInfo if (custom.isDefinedAt(targetType, json)) { custom(targetType, json) } else thunk(json) } private[this] def convert(key: String, target: ScalaType, formats: Formats): Any = { val targetType = target.erasure targetType match { case tt if tt == classOf[String] => key case tt if tt == classOf[Symbol] => Symbol(key) case tt if tt == classOf[Int] => key.toInt case tt if tt == classOf[JavaInteger] => new JavaInteger(key.toInt) case tt if tt == classOf[BigInt] => key.toInt case tt if tt == classOf[Long] => key.toLong case tt if tt == classOf[JavaLong] => new JavaLong(key.toLong) case tt if tt == classOf[Short] => key.toShort case tt if tt == classOf[JavaShort] => new JavaShort(key.toShort) case tt if tt == classOf[Date] => formatDate(key, formats) case tt if tt == classOf[Timestamp] => formatTimestamp(key, formats) case _ => val deserializer = formats.customKeyDeserializer(formats) val typeInfo = TypeInfo(targetType, None) if(deserializer.isDefinedAt((typeInfo, key))) { deserializer((typeInfo, key)) } else { fail("Do not know how to deserialize key of type " + targetType + ". Consider implementing a CustomKeyDeserializer.") } } } private[this] def convert(json: JValue, target: ScalaType, formats: Formats, default: Option[() => Any]): Any = { val targetType = target.erasure json match { case JInt(x) if (targetType == classOf[Int]) => x.intValue case JInt(x) if (targetType == classOf[JavaInteger]) => new JavaInteger(x.intValue) case JInt(x) if (targetType == classOf[BigInt]) => x case JInt(x) if (targetType == classOf[Long]) => x.longValue case JInt(x) if (targetType == classOf[JavaLong]) => new JavaLong(x.longValue) case JInt(x) if (targetType == classOf[Double]) => x.doubleValue case JInt(x) if (targetType == classOf[JavaDouble]) => new JavaDouble(x.doubleValue) case JInt(x) if (targetType == classOf[Float]) => x.floatValue case JInt(x) if (targetType == classOf[JavaFloat]) => new JavaFloat(x.floatValue) case JInt(x) if (targetType == classOf[Short]) => x.shortValue case JInt(x) if (targetType == classOf[JavaShort]) => new JavaShort(x.shortValue) case JInt(x) if (targetType == classOf[Byte]) => x.byteValue case JInt(x) if (targetType == classOf[JavaByte]) => new JavaByte(x.byteValue) case JInt(x) if (targetType == classOf[String]) => x.toString case JInt(x) if (targetType == classOf[Number]) => x.longValue case JInt(x) if (targetType == classOf[BigDecimal]) => BigDecimal(x) case JInt(x) if (targetType == classOf[JavaBigDecimal]) => BigDecimal(x).bigDecimal case JLong(x) if (targetType == classOf[Int]) => x.intValue case JLong(x) if (targetType == classOf[JavaInteger]) => new JavaInteger(x.intValue) case JLong(x) if (targetType == classOf[BigInt]) => x case JLong(x) if (targetType == classOf[Long]) => x.longValue case JLong(x) if (targetType == classOf[JavaLong]) => new JavaLong(x.longValue) case JLong(x) if (targetType == classOf[Double]) => x.doubleValue case JLong(x) if (targetType == classOf[JavaDouble]) => new JavaDouble(x.doubleValue) case JLong(x) if (targetType == classOf[Float]) => x.floatValue case JLong(x) if (targetType == classOf[JavaFloat]) => new JavaFloat(x.floatValue) case JLong(x) if (targetType == classOf[Short]) => x.shortValue case JLong(x) if (targetType == classOf[JavaShort]) => new JavaShort(x.shortValue) case JLong(x) if (targetType == classOf[Byte]) => x.byteValue case JLong(x) if (targetType == classOf[JavaByte]) => new JavaByte(x.byteValue) case JLong(x) if (targetType == classOf[String]) => x.toString case JLong(x) if (targetType == classOf[Number]) => x.longValue case JLong(x) if (targetType == classOf[BigDecimal]) => BigDecimal(x) case JLong(x) if (targetType == classOf[JavaBigDecimal]) => BigDecimal(x).bigDecimal case JDouble(x) if (targetType == classOf[Double]) => x case JDouble(x) if (targetType == classOf[JavaDouble]) => new JavaDouble(x) case JDouble(x) if (targetType == classOf[Float]) => x.floatValue case JDouble(x) if (targetType == classOf[JavaFloat]) => new JavaFloat(x.floatValue) case JDouble(x) if (targetType == classOf[String]) => x.toString case JDouble(x) if (targetType == classOf[Int]) => x.intValue case JDouble(x) if (targetType == classOf[Long]) => x.longValue case JDouble(x) if (targetType == classOf[Number]) => x case JDouble(x) if (targetType == classOf[BigDecimal]) => BigDecimal(x) case JDouble(x) if (targetType == classOf[JavaBigDecimal]) => BigDecimal(x).bigDecimal case JDecimal(x) if (targetType == classOf[Double]) => x.doubleValue() case JDecimal(x) if (targetType == classOf[JavaDouble]) => new JavaDouble(x.doubleValue()) case JDecimal(x) if (targetType == classOf[BigDecimal]) => x case JDecimal(x) if (targetType == classOf[JavaBigDecimal]) => x.bigDecimal case JDecimal(x) if (targetType == classOf[Float]) => x.floatValue case JDecimal(x) if (targetType == classOf[JavaFloat]) => new JavaFloat(x.floatValue) case JDecimal(x) if (targetType == classOf[String]) => x.toString case JDecimal(x) if (targetType == classOf[Int]) => x.intValue case JDecimal(x) if (targetType == classOf[Long]) => x.longValue case JDecimal(x) if (targetType == classOf[Number]) => x case JString(s) if (targetType == classOf[String]) => s case JString(s) if (targetType == classOf[Symbol]) => Symbol(s) case JString(s) if (targetType == classOf[Date]) => formatDate(s, formats) case JString(s) if (targetType == classOf[Timestamp]) => formatTimestamp(s, formats) case JBool(x) if (targetType == classOf[Boolean]) => x case JBool(x) if (targetType == classOf[JavaBoolean]) => new JavaBoolean(x) case j: JValue if (targetType == classOf[JValue]) => j case j: JObject if (targetType == classOf[JObject]) => j case j: JArray if (targetType == classOf[JArray]) => j case JNull if formats.allowNull => null case JNull if !formats.allowNull => fail("Did not find value which can be converted into " + targetType.getName) case JNothing => default map (_.apply()) getOrElse fail("Did not find value which can be converted into " + targetType.getName) case _ => val custom = formats.customDeserializer(formats) val typeInfo = target.typeInfo if (custom.isDefinedAt(typeInfo, json)) custom(typeInfo, json) else fail("Do not know how to convert " + json + " into " + targetType) } } private[this] def formatTimestamp(s: String, formats: Formats): Timestamp = { new Timestamp(formats.dateFormat.parse(s).getOrElse(fail("Invalid date '" + s + "'")).getTime) } private[this] def formatDate(s: String, formats: Formats): Date = { formats.dateFormat.parse(s).getOrElse(fail("Invalid date '" + s + "'")) } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy