Scala-Circe-没有类名的案例类序列化

时间:2018-10-01 15:33:23

标签: json scala shapeless circe

我以前使用过Circe进行案例类序列化/反序列化,并且喜欢如何在没有其他Scala JSON库所需的样板代码的情况下使用它,但是现在遇到了一个问题,我不是确定如何解决。我有一个ADT(带有几个case类实例的密封特征),我想(从我的Akka Http服务使用akka-http-json)对其进行一般性处理(即返回一个List[Foo],其中{{1 }}是特征类型),但是当我使用Circe的自动推导(通过Shapeless)这样做时,它将使用特定的案例类名称作为“ discriminator”(例如,如果我的Foo包含List[Foo]实例,则结果序列化列表中的每个元素都将具有键Foo1)。我想消除类型名称作为区分符(即,为了使序列中的每个元素都没有前缀类型名称,例如Foo1,我只想序列化要包含的case类实例案例类的字段:例如,"Foo1": {"id : "1", name : "First",...} ...基本上,我想消除类型名称键(我不希望前端必须知道每个元素属于哪个具体案例类)

要序列化的列表中的所有元素都将是相同的具体类型,所有这些都将是我的ADT(特征)类型的子类型。可以使用Circe的半自动推导完成,尽管我没有机会确切地知道如何操作。基本上,我想尽可能多地使用Circe的自动推导,但是要避免出现外层类名在产生的JSON中。任何帮助/建议将不胜感激!谢谢!

2 个答案:

答案 0 :(得分:1)

您可以按照文档中的说明进行操作:https://circe.github.io/circe/codecs/adt.html

import cats.syntax.functor._
import io.circe.{ Decoder, Encoder }, io.circe.generic.auto._
import io.circe.syntax._

object GenericDerivation {
  implicit val encodeEvent: Encoder[Event] = Encoder.instance {
    case foo @ Foo(_) => foo.asJson
    case bar @ Bar(_) => bar.asJson
    case baz @ Baz(_) => baz.asJson
    case qux @ Qux(_) => qux.asJson
  }

  implicit val decodeEvent: Decoder[Event] =
    List[Decoder[Event]](
      Decoder[Foo].widen,
      Decoder[Bar].widen,
      Decoder[Baz].widen,
      Decoder[Qux].widen
    ).reduceLeft(_ or _)
}

import GenericDerivation._
import io.circe.parser.decode

decode[Event]("""{ "i": 1000 }""")
// res0: Either[io.circe.Error,Event] = Right(Foo(1000))

(Foo(100): Event).asJson.noSpaces
// res1: String = {"i":100}

答案 1 :(得分:0)

这可能不是最佳答案,但是经过更多搜索之后,这才是我能够找到的。可以不用将类名作为生成的Json的键,而可以将其序列化为以下字段:

implicit val genDevConfig: Configuration.default.withDescriminator("type")

(您可以在此处使用任何字段名称;对于类似的问题,Travis Brown的上一个example使用了名为what_am_i的字段)。因此,我深表歉意–我尚不知道是否存在针对该问题的规范或广泛接受的解决方案,尤其是使用akka-http-json之类的库可以轻松地与Akka Http一起使用的解决方案,我似乎仍然在遇到一些问题,尽管我确定我可能会忽略一些明显的问题!无论如何,我很抱歉提出一个似乎反复出现的问题!