Skip to content

Instantly share code, notes, and snippets.

@dcsobral
Created July 2, 2012 03:59
Show Gist options
  • Save dcsobral/3030995 to your computer and use it in GitHub Desktop.
Save dcsobral/3030995 to your computer and use it in GitHub Desktop.
JSON serialization
import scala.reflect.runtime.universe._
import scala.collection.GenTraversableOnce
case class Numero(n: Int, s: String)
case class Xyzzy(lst: List[Int])
case class Nested(nums: List[Numero], xyzzy: Xyzzy)
object Test extends App {
def serialize[T: TypeTag](obj: T): String = {
def doSerialize(obj: Any, objType: Type, nesting: Int = 1): String = {
val ts = " " * nesting
val prevts = " " * (nesting - 1)
def serializeObject(obj: Any, objType: Type): String = {
val mirror = runtimeMirror(obj.getClass.getClassLoader)
def serializationOfGetter(fieldSymbol: Symbol): String = {
val valueOfGetter = (
mirror reflect obj
reflectMethod fieldSymbol.asMethodSymbol
).apply()
val NullaryMethodType(fieldType) = fieldSymbol typeSignatureIn objType
doSerialize(valueOfGetter, fieldType, nesting + 1)
}
val fields = objType.nonPrivateMembers filter (_.isGetter)
fields map {
f => s""""${f.name.toString}": ${serializationOfGetter(f)}"""
} mkString ( s"{\n$ts", s",\n$ts", s"\n$prevts}")
}
if (objType <:< StringTpe) s""""$obj""""
else if (objType <:< AnyValTpe) obj.toString
else if (objType.baseType(typeOf[GenTraversable[_]].typeSymbol) != NoType) {
val refinedType = objType.baseType(typeOf[GenTraversable[_]].typeSymbol)
val argumentType = refinedType.typeArguments.head
(
obj.asI[GenTraversable[_]].toSeq
map (doSerialize(_, argumentType, nesting + 1))
mkString ( s"[\n$ts", s",\n$ts", s"\n$prevts]")
)
} else {
serializeObject(obj, objType)
}
}
doSerialize(obj, typeOf[T])
}
val num = Numero(2, "b")
val xyzzy = Xyzzy(List(1,2,3))
val nested = Nested(List(num, num), xyzzy)
println(serialize(num))
println(serialize(xyzzy))
println(serialize(nested))
println(serialize(1))
println(serialize("abc"))
println(serialize((1,"a")))
println(serialize(Map(1 -> "a", 2 -> "b")))
}
def serialize[T : TypeTag](obj: T): String = {
def recurse(obj: Any, objType: Type): String = {
if (objType <:< StringTpe) s""""$obj""""
else if (objType <:< AnyValTpe) obj.toString
else if (objType.baseType(typeOf[GenTraversable[_]].typeSymbol) != NoType) {
val refinedType = objType.baseType(typeOf[GenTraversable[_]].typeSymbol)
val argumentType = refinedType.typeArguments.head
val objAsColl = obj.asInstanceOf[GenTraversable[_]]
val recursedSeq = objAsColl map (recurse(_, argumentType))
recursedSeq.mkString("[ ", ", ", " ]")
} else "Unknown"
}
recurse(obj, typeOf[T])
}
def serialize(obj: Any): String = {
val mirror = runtimeMirror(obj.getClass.getClassLoader)
val objType = mirror.classSymbol(obj.getClass).typeSignature
val StringTpe = mirror.classSymbol(classOf[String]).typeSignature
val AnyValTpe = mirror.classSymbol(classOf[AnyVal]).typeSignature
if (objType <:< StringTpe) s""""$obj""""
else if (objType <:< AnyValTpe) obj.toString // DOES NOT WORK!!!
else if (objType.baseType(typeOf[GenTraversable[_]].typeSymbol) != NoType) {
val refinedType = objType.baseType(typeOf[GenTraversable[_]].typeSymbol)
val argumentType = refinedType.typeArguments.head
val objAsColl = obj.asInstanceOf[GenTraversable[_]]
val recursedSeq = objAsColl map serialize
recursedSeq.mkString("[ ", ", ", " ]")
} else "Unknown"
}
val obj = "String"
val objClass = obj.getClass
val classClassLoader = objClass.getClassLoader
val classLoaderMirror = runtimeMirror(classClassLoader)
val classSymbol = classLoaderMirror.classSymbol(objClass)
val classType = classSymbol.typeSignature
val methodName = newTermName("length")
val methodSymbol = classType.member(methodName).asMethodSymbol
val instanceMirror = classLoaderMirror.reflect(obj)
val methodMirror = instanceMirror.reflectMethod(methodSymbol)
methodMirror.apply()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment