Created
July 2, 2012 03:59
-
-
Save dcsobral/3030995 to your computer and use it in GitHub Desktop.
JSON serialization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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