Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Improve search of FieldSerializers: examine the class hierarchy

  • Loading branch information...
commit 5d2c87f39a4ffd321756afb9989850e2e2814382 1 parent e00bbf0
Joni Freeman authored
View
43 core/json/src/main/scala/net/liftweb/json/Formats.scala
@@ -29,7 +29,7 @@ trait Formats { self: Formats =>
val dateFormat: DateFormat
val typeHints: TypeHints = NoTypeHints
val customSerializers: List[Serializer[_]] = Nil
- val fieldSerializers: Map[Class[_], FieldSerializer[_]] = Map()
+ val fieldSerializers: List[(Class[_], FieldSerializer[_])] = Nil
/**
* The name of the field in JSON where type hints are added (jsonClass by default)
@@ -77,11 +77,18 @@ trait Formats { self: Formats =>
override val parameterNameReader = self.parameterNameReader
override val typeHints = self.typeHints
override val customSerializers = self.customSerializers
- override val fieldSerializers = self.fieldSerializers.updated(mf.erasure, newSerializer)
+ override val fieldSerializers = (mf.erasure, newSerializer) :: self.fieldSerializers
}
- private[json] def fieldSerializer(clazz: Class[_]): Option[FieldSerializer[_]] =
- fieldSerializers.get(clazz)
+ private[json] def fieldSerializer(clazz: Class[_]): Option[FieldSerializer[_]] = {
+ import ClassDelta._
+
+ val ord = Ordering[Int].on[(Class[_], FieldSerializer[_])](x => delta(x._1, clazz))
+ fieldSerializers filter (_._1.isAssignableFrom(clazz)) match {
+ case Nil => None
+ case xs => Some((xs min ord)._2)
+ }
+ }
def customSerializer(implicit format: Formats) =
customSerializers.foldLeft(Map(): PartialFunction[Any, JValue]) { (acc, x) =>
@@ -126,6 +133,8 @@ trait Serializer[A] {
* </pre>
*/
trait TypeHints {
+ import ClassDelta._
+
val hints: List[Class[_]]
/** Return hint for given type.
@@ -166,19 +175,21 @@ trait TypeHints {
override def serialize: PartialFunction[Any, JObject] = components.foldLeft[PartialFunction[Any, JObject]](Map()) {
(result, cur) => result.orElse(cur.serialize)
}
-
- private def delta(class1: Class[_], class2: Class[_]): Int = {
- if (class1 == class2) 0
- else if (class1.getInterfaces.contains(class2)) 0
- else if (class2.getInterfaces.contains(class1)) 0
- else if (class1.isAssignableFrom(class2)) {
- 1 + delta(class1, class2.getSuperclass)
- }
- else if (class2.isAssignableFrom(class1)) {
- 1 + delta(class1.getSuperclass, class2)
- }
- else error("Don't call delta unless one class is assignable from the other")
+ }
+}
+
+private[json] object ClassDelta {
+ def delta(class1: Class[_], class2: Class[_]): Int = {
+ if (class1 == class2) 0
+ else if (class1.getInterfaces.contains(class2)) 0
+ else if (class2.getInterfaces.contains(class1)) 0
+ else if (class1.isAssignableFrom(class2)) {
+ 1 + delta(class1, class2.getSuperclass)
+ }
+ else if (class2.isAssignableFrom(class1)) {
+ 1 + delta(class1.getSuperclass, class2)
}
+ else error("Don't call delta unless one class is assignable from the other")
}
}
View
18 core/json/src/test/scala/net/liftweb/json/FieldSerializerExamples.scala
@@ -27,6 +27,9 @@ object FieldSerializerExamples extends Specification {
dog.name = "pluto"
dog.owner = Owner("joe", 35)
+ val cat = new WildCat(100)
+ cat.name = "tommy"
+
"All fields are serialized by default" in {
implicit val formats = DefaultFormats + FieldSerializer[WildDog]()
val ser = swrite(dog)
@@ -53,6 +56,17 @@ object FieldSerializerExamples extends Specification {
dog2.size mustEqual dog.size
(parse(ser) \ "animalname") mustEqual JString("pluto")
}
+
+ "Selects best matching serializer" in {
+ val dogSerializer = FieldSerializer[WildDog](ignore("name"))
+ implicit val formats = DefaultFormats + FieldSerializer[AnyRef]() + dogSerializer
+
+ val dog2 = read[WildDog](swrite(dog))
+ val cat2 = read[WildCat](swrite(cat))
+
+ dog2.name mustEqual ""
+ cat2.name mustEqual "tommy"
+ }
}
abstract class Mammal {
@@ -61,7 +75,7 @@ abstract class Mammal {
val size = List(10, 15)
}
-class WildDog(val color: String) extends Mammal {
-}
+class WildDog(val color: String) extends Mammal
+class WildCat(val cuteness: Int) extends Mammal
case class Owner(name: String, age: Int)
Please sign in to comment.
Something went wrong with that request. Please try again.