如何使用Scala中的任何库将通用的可能嵌套的映射Map [String,Any]转换为case类? [英] How to convert generic potentially nested map Map[String, Any] to case class using any library in Scala?

查看:138
本文介绍了如何使用Scala中的任何库将通用的可能嵌套的映射Map [String,Any]转换为case类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对反射没有太大的兴趣,这个答案在某些情况下使用无形状的作品(但似乎有很多边缘情况)

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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆