【发布时间】:2017-02-19 18:41:16
【问题描述】:
我有一个 Scala 映射,其键控类型本身需要序列化为 JSON。由于 JSON 的性质要求对象的键名是字符串,因此无法直接进行简单的映射。
我希望实现的解决方法是在序列化为 JSON 之前将 Map 转换为 Set,然后在反序列化后从 Set 转换回 Map。
我知道在 特定 类型上使用密钥序列化程序的其他方法,例如Serialising Map with Jackson,然而,我需要一个适用于任意键类型的解决方案,在这方面,转换为 Set 并再次返回在我看来是最好的选择。
通过从下面的jackson-module-scala 修改MapSerializerModule.scala,我已经成功地将带有包装对象的 Set 序列化为 Set,但我对 Jackson 内部结构不够熟悉,无法将该 JSON 反序列化回 Map I开始。
我应该补充一点,我同时控制序列化和反序列化,所以 JSON 看起来并不重要。
case class Wrapper[K, V](
value: Set[(K, V)]
)
class MapConverter[K, V](inputType: JavaType, config: SerializationConfig)
extends StdConverter[Map[K, V], Wrapper[K, V]] {
def convert(value: Map[K, V]): Wrapper[K, V] = {
val set = value.toSet
Wrapper(set)
}
override def getInputType(factory: TypeFactory) = inputType
override def getOutputType(factory: TypeFactory) =
factory.constructReferenceType(classOf[Wrapper[_, _]], inputType.getContentType)
.withTypeHandler(inputType.getTypeHandler)
.withValueHandler(inputType.getValueHandler)
}
object MapSerializerResolver extends Serializers.Base {
val MAP = classOf[Map[_, _]]
override def findMapLikeSerializer(
config: SerializationConfig,
typ: MapLikeType,
beanDesc: BeanDescription,
keySerializer: JsonSerializer[AnyRef],
elementTypeSerializer: TypeSerializer,
elementValueSerializer: JsonSerializer[AnyRef]): JsonSerializer[_] = {
val rawClass = typ.getRawClass
if (!MAP.isAssignableFrom(rawClass)) null
else new StdDelegatingSerializer(new MapConverter(typ, config))
}
}
object Main {
def main(args: Array[String]): Unit = {
val objMap = Map(
new Key("k1", "k2") -> "k1k2",
new Key("k2", "k3") -> "k2k3")
val om = new ObjectMapper()
om.registerModule(DefaultScalaModule)
om.registerModule(ConverterModule)
val res = om.writeValueAsString(objMap)
println(res)
}
}
【问题讨论】:
-
我给你的答案是没有答案:注解和运行时反射是万恶之源。离开那个世界,转向基于类型类的方法
标签: json scala jackson jackson-module-scala