标签: circe

如何使用circe解码ADT而不消除对象的歧义

假设我有这样的ADT:

sealed trait Event

case class Foo(i: Int) extends Event
case class Bar(s: String) extends Event
case class Baz(c: Char) extends Event
case class Qux(values: List[String]) extends Event
Run Code Online (Sandbox Code Playgroud)

circe中Decoder[Event]实例的默认泛型推导要求输入JSON包含一个包装器对象,该对象指示表示的是哪个case类:

scala> import io.circe.generic.auto._, io.circe.parser.decode, io.circe.syntax._
import io.circe.generic.auto._
import io.circe.parser.decode
import io.circe.syntax._

scala> decode[Event]("""{ "i": 1000 }""")
res0: Either[io.circe.Error,Event] = Left(DecodingFailure(CNil, List()))

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

scala> (Foo(100): Event).asJson.noSpaces
res2: String = {"Foo":{"i":100}}
Run Code Online (Sandbox Code Playgroud)

这种行为意味着如果两个或多个案例类具有相同的成员名称,我们就不必担心含糊不清,但它并不总是我们想要的 - 有时我们知道展开的编码是明确的,或者我们想要通过指定顺序来消除歧义应该尝试每个案例类,或者我们只是不在乎.

如何在Event没有包装器的情况下对ADT 进行编码和解码(最好不必从头开始编写我的编码器和解码器)?

(这个问题经常出现 - 例如今天早上 …

json scala algebraic-data-types circe generic-derivation

26
推荐指数
1
解决办法
4306
查看次数

如何使用 circe 将密封的 trait case 对象转换为字符串

我正在使用 Scala 和 Circe。我有以下密封特征。

  sealed trait Mode
  case object Authentication extends Mode
  case object Ocr extends Mode
Run Code Online (Sandbox Code Playgroud)

调用此 case 对象时的输出SessionModel.Authentication如下:

"Authentication":{}
Run Code Online (Sandbox Code Playgroud)

我需要将其转换为字符串以便输出 "authentication"

scala circe

14
推荐指数
1
解决办法
2674
查看次数

用于编码/解码arity 0的密封特征实例的Circe实例?

我使用密封特性作为详尽模式匹配的枚举.如果我有case对象而不是扩展我的特性的case类,我想编码和解码(通过Circe)只是一个普通的字符串.

例如:

sealed trait State
case object On extends State
case object Off extends State

val a: State = State.Off
a.asJson.noSpaces // trying for "Off"

decode[State]("On") // should be State.On
Run Code Online (Sandbox Code Playgroud)

我知道这可以在0.5.0中配置,但任何人都可以帮我写一些东西来帮助我,直到它被释放?

scala circe

13
推荐指数
1
解决办法
7261
查看次数

我的coproduct编码不明确

这个问题最近出现了几次,所以我在这里常见问题.假设我有一些像这样的案例类:

import io.circe._, io.circe.generic.semiauto._

object model {
  case class A(a: String)
  case class B(a: String, i: Int)
  case class C(i: Int, b: Boolean)

  implicit val encodeA: Encoder[A] = deriveEncoder
  implicit val encodeB: Encoder[B] = deriveEncoder
  implicit val encodeC: Encoder[C] = deriveEncoder
  implicit val decodeA: Decoder[A] = deriveDecoder
  implicit val decodeB: Decoder[B] = deriveDecoder
  implicit val decodeC: Decoder[C] = deriveDecoder
}
Run Code Online (Sandbox Code Playgroud)

我想使用circe和Shapeless副产品对一个值进行编码,这些值可以是JSON中的任何一个.

import io.circe.shapes._, io.circe.syntax._
import shapeless._

import model._

type ABC = A :+: B :+: C :+: CNil …
Run Code Online (Sandbox Code Playgroud)

union json scala circe coproduct

13
推荐指数
1
解决办法
514
查看次数

使用Scala中的circe解码结构化JSON数组

假设我需要解码如下所示的JSON数组,其中开头有几个字段,一些任意数量的同类元素,然后是其他一些字段:

[ "Foo", "McBar", true, false, false, false, true, 137 ]
Run Code Online (Sandbox Code Playgroud)

我不知道为什么有人会选择像这样编码他们的数据,但人们做了奇怪的事情,并且假设在这种情况下我只需要处理它.

我想将这个JSON解码为这样的案例类:

case class Foo(firstName: String, lastName: String, age: Int, stuff: List[Boolean])
Run Code Online (Sandbox Code Playgroud)

我们可以这样写:

import cats.syntax.either._
import io.circe.{ Decoder, DecodingFailure, Json }

implicit val fooDecoder: Decoder[Foo] = Decoder.instance { c =>
  c.focus.flatMap(_.asArray) match {
    case Some(fnJ +: lnJ +: rest) =>
      rest.reverse match {
        case ageJ +: stuffJ =>
          for {
            fn    <- fnJ.as[String]
            ln    <- lnJ.as[String]
            age   <- ageJ.as[Int]
            stuff <- Json.fromValues(stuffJ.reverse).as[List[Boolean]]
          } yield Foo(fn, ln, age, stuff)
        case …
Run Code Online (Sandbox Code Playgroud)

json scala circe

13
推荐指数
1
解决办法
2117
查看次数

在circe中将所有键从`下划线'转换为`camel case`的json对象

起源

{
  "first_name" : "foo",
  "last_name" : "bar",
  "parent" : {
    "first_name" : "baz",
    "last_name" : "bazz",
  }
}
Run Code Online (Sandbox Code Playgroud)

预期

 {
      "firstName" : "foo",
      "lastName" : "bar",
      "parent" : {
        "firstName" : "baz",
        "lastName" : "bazz",
      }
    }
Run Code Online (Sandbox Code Playgroud)

如何转换json对象的所有键?

json scala circe

12
推荐指数
1
解决办法
3353
查看次数

使用Circe Json,为什么隐式解析在运行时会变慢

与将隐式解码器保存为val相比,为什么Circe Json使用隐式解码器查找更慢.

我希望这些是相同的,因为隐式解析是在运行时完成的.

import io.circe._
import io.circe.generic.auto._
import io.circe.jackson
import io.circe.syntax._

private val decoder = implicitly[Decoder[Data.Type]]
def decode(): Either[Error, Type] = {
  jackson.decode[Data.Type](Data.json)(decoder)
}

def decodeAuto(): Either[Error, Type] = {
  jackson.decode[Data.Type](Data.json)
}


[info] DecodeTest.circeJackson             thrpt  200   69157.472 ± 283.285  ops/s
[info] DecodeTest.circeJacksonAuto         thrpt  200   67946.734 ± 315.876  ops/s
Run Code Online (Sandbox Code Playgroud)

完整的回购可以在这里找到. https://github.com/stephennancekivell/some-jmh-json-benchmarks-circe-jackson

json scala circe

11
推荐指数
1
解决办法
796
查看次数

使用circe解码JSON对象时捕获未使用的字段

假设我有一个类似下面的案例类,我想将一个JSON对象解码到其中,所有未使用的字段最终都留在剩余的特殊成员中:

import io.circe.Json

case class Foo(a: Int, b: String, leftovers: Json)
Run Code Online (Sandbox Code Playgroud)

使用circe在Scala中执行此操作的最佳方法是什么?

(注意:我已经看过几次这样的问题,所以我为后人做了Q-and-A-ing.)

json scala decoding circe

11
推荐指数
1
解决办法
422
查看次数

使用Argonaut或Circe更新不完整JSON的案例类

我需要从一个case类实例创建一个更新的实例(带有任何需要DecodeJson的隐式派生),给定一个不完整的json(缺少一些字段).如何通过Argonaut(最好)或Circe(如果必须的话)实现这一目标?

例:

case class Person(name:String, age:Int)
val person = Person("mr complete", 42)
val incompletePersonJson = """{"name":"mr updated"}"""
val updatedPerson = updateCaseClassFromIncompleteJson(person, incompletePersonJson)

println(updatedPerson)
//yields Person(mr updated, 42) 
Run Code Online (Sandbox Code Playgroud)

我很确定我必须将json解析为json AST,然后将其转换为Shapeless LabelledGeneric,然后以某种方式使用Shapeless更新来更新case类实例.


编辑2

在阅读了Shapeless源代码后,我发现我可以生成自己的"默认"对象.我设法创建了一个解决方案,它需要在解析json时出现case类的实例.我希望避免这种情况,而是稍后提供实例.无论如何它是:

import shapeless._
import argonaut._
import ArgonautShapeless._
import shapeless.ops.hlist.Mapper

case class Person(name: String, age: Int)

object MkDefault {

  object toSome extends Poly1 {
    implicit def default[P] = at[P](Some(_))
  }

  def apply[P, L <: HList, D <: HList]
  (p: P)
  (implicit
   g: Generic.Aux[P, L],
   mpr: Mapper.Aux[toSome.type, L, …
Run Code Online (Sandbox Code Playgroud)

json scala shapeless argonaut circe

10
推荐指数
1
解决办法
1480
查看次数

Scala中ADT的通用派生,具有自定义表示

我在这里解释了来自Circe Gitter频道的一个问题.

假设我有一个像这样的Scala密封特征层次结构(或ADT):

sealed trait Item
case class Cake(flavor: String, height: Int) extends Item
case class Hat(shape: String, material: String, color: String) extends Item
Run Code Online (Sandbox Code Playgroud)

...我希望能够在此ADT和JSON表示之间来回映射,如下所示:

{ "tag": "Cake", "contents": ["cherry", 100] }
{ "tag": "Hat", "contents": ["cowboy", "felt", "black"] }
Run Code Online (Sandbox Code Playgroud)

默认情况下,circe的泛型推导使用不同的表示:

scala> val item1: Item = Cake("cherry", 100)
item1: Item = Cake(cherry,100)

scala> val item2: Item = Hat("cowboy", "felt", "brown")
item2: Item = Hat(cowboy,felt,brown)

scala> import io.circe.generic.auto._, io.circe.syntax._
import io.circe.generic.auto._
import io.circe.syntax._

scala> item1.asJson.noSpaces
res0: String = {"Cake":{"flavor":"cherry","height":100}} …
Run Code Online (Sandbox Code Playgroud)

json scala circe generic-derivation

9
推荐指数
1
解决办法
388
查看次数