如何使用Scala中的任何库将通用的可能嵌套的映射Map [String,Any]转换为case类? [英] How to convert generic potentially nested map Map[String, Any] to case class using any library in Scala?
问题描述
我对反射没有太大的兴趣,这个答案在某些情况下使用无形状的作品(但似乎有很多边缘情况)
I've not had much joy with reflection, this answer using shapeless works for some cases (but seems to have many edge cases) Shapeless code to convert Map[String, Any] to case class cannot handle optional substructures
有人知道只有一个LOC才能做到这一点的好库吗?
Does anyone know of a nice library that does this in just a few LOCs?
推荐答案
我们可以使用circe
We can use circe
import io.circe._
import io.circe.generic.auto._
import io.circe.parser._
import io.circe.syntax._
def mapToJson(map: Map[String, Any]): Json =
map.mapValues(anyToJson).asJson
def anyToJson(any: Any): Json = any match {
case n: Int => n.asJson
case n: Long => n.asJson
case n: Double => n.asJson
case s: String => s.asJson
case true => true.asJson
case false => false.asJson
case null | None => None.asJson
case list: List[_] => list.map(anyToJson).asJson
case list: Vector[_] => list.map(anyToJson).asJson
case Some(any) => anyToJson(any)
case map: Map[String, Any] => mapToJson(map)
}
def mapToCaseClass[T : Decoder](map: Map[String, Any]): T = mapToJson(map).as[T].right.get
然后,如果我们有任何不是原始类型的类型,我们只需要将它们与可以将这种类型编码/解码为原始类型的编码器/解码器对一起添加到我们的anyToJson
中即可.
Then, if we have any types that are not primitive, we just need to add these to our anyToJson
along with an encoder/decoder pair that can encode/decode this type as something primitive.
例如我们可以用Long
表示java.sql.Timestamp
,然后
E.g. we can represent java.sql.Timestamp
with Long
, then
import cats.syntax.either._
import io.circe.Decoder
import io.circe.Encoder
implicit val decodeTimestamp: Decoder[Timestamp] = Decoder.decodeLong.emap(long =>
Either.catchNonFatal(new Timestamp(long)).leftMap(_ => "Timestamp")
)
implicit val encodeTimestamp: Encoder[Timestamp] = Encoder.encodeLong.contramap[Timestamp](_.getTime)
,我们需要将行添加到anyToJson
and we need to add the line to anyToJson
case n: Timestamp => n.asJson
这篇关于如何使用Scala中的任何库将通用的可能嵌套的映射Map [String,Any]转换为case类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!