Skip to content

Instantly share code, notes, and snippets.

@dyno
Created November 14, 2021 03:47
Show Gist options
  • Save dyno/42c3837495f314007f4113a4c6a5e629 to your computer and use it in GitHub Desktop.
Save dyno/42c3837495f314007f4113a4c6a5e629 to your computer and use it in GitHub Desktop.
Gson Adapter for Scala
import com.google.gson._
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
import java.lang.reflect.{ParameterizedType, Type}
import java.util.{ArrayList => JArrayList, LinkedHashMap => JListMap, List => JList}
import scala.collection.JavaConverters._
import scala.collection.immutable.ListMap
object GsonAdapter {
lazy val gson = (new GsonBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.registerTypeAdapter(classOf[ListMap[_, _]], ListMapAdapter)
.registerTypeAdapter(classOf[Option[_]], OptionAdapter)
.registerTypeAdapter(classOf[Seq[_]], SeqAdapter)
.create())
def getInnerTypes(outerType: Type): Array[Type] =
outerType match {
case pt: ParameterizedType => pt.getActualTypeArguments()
case _ => throw new UnsupportedOperationException(outerType.toString)
}
object ListMapAdapter extends JsonSerializer[ListMap[_, _]] with JsonDeserializer[ListMap[_, _]] {
override def serialize(obj: ListMap[_, _], typeOfT: Type, context: JsonSerializationContext): JsonElement = {
val innerTypes = getInnerTypes(typeOfT)
val pt = ParameterizedTypeImpl.make(classOf[JListMap[_, _]], innerTypes, null)
val jListMap = new JListMap[Any, Any]()
obj.foreach { case (k, v) => jListMap.put(k, v) }
context.serialize(jListMap, pt)
}
override def deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): ListMap[_, _] = {
val innerTypes = getInnerTypes(typeOfT)
val pt = ParameterizedTypeImpl.make(classOf[JListMap[_, _]], innerTypes, null)
val jListMap: JListMap[_, _] = context.deserialize(json, pt)
ListMap(jListMap.asScala.toSeq: _*)
}
}
object OptionAdapter extends JsonSerializer[Option[_]] with JsonDeserializer[Option[_]] {
override def serialize(obj: Option[_], typeOfT: Type, context: JsonSerializationContext): JsonElement = {
val jList = new JArrayList[Any]()
obj.foreach(jList.add)
val innerTypes = getInnerTypes(typeOfT)
val pt = ParameterizedTypeImpl.make(classOf[JList[_]], innerTypes, null)
context.serialize(jList, pt)
}
override def deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Option[_] = {
val innerTypes = getInnerTypes(typeOfT)
val pt = ParameterizedTypeImpl.make(classOf[JList[_]], innerTypes, null)
val jList: JList[_] = context.deserialize(json, pt)
jList.asScala.headOption
}
}
object SeqAdapter extends JsonSerializer[Seq[_]] with JsonDeserializer[Seq[_]] {
override def serialize(obj: Seq[_], typeOfT: Type, context: JsonSerializationContext): JsonElement = {
val jList = new JArrayList[Any]()
jList.addAll(obj.asJava)
val innerTypes = getInnerTypes(typeOfT)
val pt = ParameterizedTypeImpl.make(classOf[JList[_]], innerTypes, null)
context.serialize(jList, pt)
}
override def deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Seq[_] = {
val innerTypes = getInnerTypes(typeOfT)
val pt = ParameterizedTypeImpl.make(classOf[JList[_]], innerTypes, null)
val jList: JList[_] = context.deserialize(json, pt)
jList.asScala.toSeq
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment