假设我有这样的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 进行编码和解码(最好不必从头开始编写我的编码器和解码器)?
(这个问题经常出现 - 例如今天早上 …
我正在使用 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"
我使用密封特性作为详尽模式匹配的枚举.如果我有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中配置,但任何人都可以帮我写一些东西来帮助我,直到它被释放?
这个问题最近出现了几次,所以我在这里常见问题.假设我有一些像这样的案例类:
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) 假设我需要解码如下所示的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) 起源
{
"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对象的所有键?
与将隐式解码器保存为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对象解码到其中,所有未使用的字段最终都留在剩余的特殊成员中:
import io.circe.Json
case class Foo(a: Int, b: String, leftovers: Json)
Run Code Online (Sandbox Code Playgroud)
使用circe在Scala中执行此操作的最佳方法是什么?
我需要从一个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) 我在这里解释了来自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)