我有一个能够持久保存任何类型的方法,只要该类型有一个io.circe.Encoder[A]实例,如下所示:
def persist[A](a: A)(implicit ea: Encoder[A]): Boolean
现在在测试时,我可以在密封特性下创建任何旧案例类或一组案例类,创建一个ADT,并使用自动类型类派生来创建Encoder,并创建ScalaCheck Arbitrary实例,这使得测试非常好.
是否有可能以某种方式使用Shapeless来创建案例类的任意族(因此自动派生Encoder和Arbitrary实例),以便我可以确定我的persist方法适用于任何类型?
我不知道从哪里开始,更不用说为此描述一种类型了.
假设我想使用circe将JSON数组中的某些值解码为case类。以下工作正常:
scala> import io.circe.generic.auto._, io.circe.jawn.decode
import io.circe.generic.auto._
import io.circe.jawn.decode
scala> case class Foo(name: String)
defined class Foo
scala> val goodDoc = """[{ "name": "abc" }, { "name": "xyz" }]"""
goodDoc: String = [{ "name": "abc" }, { "name": "xyz" }]
scala> decode[List[Foo]](goodDoc)
res0: Either[io.circe.Error,List[Foo]] = Right(List(Foo(abc), Foo(xyz)))
Run Code Online (Sandbox Code Playgroud)
但是,有时候我正在解码的JSON数组包含其他非Foo形的东西,这会导致解码错误:
scala> val badDoc =
| """[{ "name": "abc" }, { "id": 1 }, true, "garbage", { "name": "xyz" }]"""
badDoc: String = [{ "name": "abc" }, { "id": …Run Code Online (Sandbox Code Playgroud) 我输入了json
{"a": "x", "b": "y", "c": "z", .... }
Run Code Online (Sandbox Code Playgroud)
我想将此 json 转换为 Map 之类的 Map[String, String]
所以基本上是键值对的映射。
我怎样才能使用 circe 做到这一点?
请注意,我不知道 Json 中将出现哪些键“a”、“b”、“c”。我所知道的是,它们将始终是字符串,而不是任何其他数据类型。
我在这里查看了自定义解码器https://circe.github.io/circe/codecs/custom-codecs.html但它们仅在您知道标签名称时才起作用。
我在杰克逊找到了一个例子来做到这一点。但不在圈子里
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.databind.ObjectMapper
val data = """
{"a": "x", "b", "y", "c": "z"}
"""
val mapper = new ObjectMapper
mapper.registerModule(DefaultScalaModule)
mapper.readValue(data, classOf[Map[String, String]])
Run Code Online (Sandbox Code Playgroud) 对于这个案例类:
import io.circe.generic.JsonCodec
@JsonCodec
case class Stuff(things: Array[String])
Run Code Online (Sandbox Code Playgroud)
此测试通过ok(case类到json测试):
import io.circe.parser.decode
import io.circe.syntax._
import org.scalatest._
val caseClass = Stuff(things = Array("one", "two"))
val json = caseClass.asJson.spaces2
json shouldEqual
"""{
| "things" : [
| "one",
| "two"
| ]
|}""".stripMargin
Run Code Online (Sandbox Code Playgroud)
然而,这是失败的(json到案例类测试)
import io.circe.parser.decode
import io.circe.syntax._
import org.scalatest._
val json =
"""{
| "things" : [
| "one",
| "two"
| ]
|}""".stripMargin
val caseClass = Right(decode[Stuff](json))
caseClass shouldEqual Stuff(things = Array("one", "two"))
Run Code Online (Sandbox Code Playgroud)
在调试器中单步执行它,似乎数组不会像我期望的那样被解码,它似乎是对象标识/内存地址,它总是不同的,所以我的测试失败了:
[Ljava.lang.String; @ 2fa7ae9
请注意,这似乎恰好发生在Arrays上,我的json blob中有很多东西我已经省略了这个例子 - Maps和嵌套的case-classes都被解码并且可以比较好,只有当Arrays被添加到比较失败 …
我有以下代码,但无法编译:
import java.time.Instant
import io.circe.{Decoder, Encoder}
import io.circe.generic.auto._
import io.circe.syntax._
trait SapHealth {}
case class SapHealthRejected(reason: String) extends SapHealth
case class SapHealthAccepted(sapId: String, requestedAt: Long) extends SapHealth
object SapHealth {
private val build: SapHealth = SapHealthAccepted(SapmockActor.system.name, Instant.now().getEpochSecond)
val create: String = build.asJson.noSpaces
implicit val encodeFieldType: Encoder[SapHealthAccepted] =
Encoder.forProduct2("sap-id", "requested_at")(SapHealthAccepted.unapply(_).get)
implicit val decodeFieldType: Decoder[SapHealthAccepted] =
Decoder.forProduct2("sap-id", "requested_at")(SapHealthAccepted.apply)
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨:
could not find implicit value for parameter encoder: io.circe.Encoder[com.sweetsoft.SapHealth]
[error] val create: String = build.asJson.noSpaces
Run Code Online (Sandbox Code Playgroud)
我缺少什么?
假设我有一些像这样的 JSON 数据:
{
"data": {
"title": "example input",
"someBoolean": false,
"innerData": {
"innerString": "input inner string",
"innerBoolean": true,
"innerCollection": [1,2,3,4,5]
},
"collection": [6,7,8,9,0]
}
}
Run Code Online (Sandbox Code Playgroud)
我想将其压平一点并转换或删除一些字段,以获得以下结果:
{
"data": {
"ttl": "example input",
"bool": false,
"collection": [6,7,8,9,0],
"innerCollection": [1,2,3,4,5]
}
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能用Circe做到这一点?
(请注意,我将此作为常见问题解答提出,因为Circe Gitter 频道中经常出现类似的问题。这个具体示例来自昨天提出的问题。)
我的问题有点棘手。我有一个像这样的案例类
case class Foo(
id: String,
name: String,
field1: Boolean,
field2: Boolean,
field3: Boolean,
field4: Boolean
)
Run Code Online (Sandbox Code Playgroud)
但是,我有两种类型的输入,一种非常适合 case class Foo。另一个是缺少field3and 的值field4,看起来
{id: "Test", name: "Test", field1: true, field2: true}我想创建一个Decoder[Foo]适用于这两种情况的值,如果缺少输入field3and field4,只需设置一个默认值false。那可能吗?
例如,
(1)对于输入{id: "Test", name: "Test", field1: true, field2: true},我想将其解码为
Foo("Test, "Test", true, true, false, flase)
Run Code Online (Sandbox Code Playgroud)
(2)对于输入{id: "Test", name: "Test", field1: true, field2: true, field3: true, field4: false},我想将其解码为
Foo("Test, "Test", true, true, true, …Run Code Online (Sandbox Code Playgroud) 我想在一行中将 json 打印为字符串。
case class Data(e: Option[String])
object Data {
implicit val dEncoder = deriveDecoder[Data]
implicit val dDecoder = deriveEncoder[Data]
}
case class Random(a: String,b: String, c: Int,d: Data)
object Random {
implicit val rEncoder = deriveDecoder[Random]
implicit val rDecoder = deriveEncoder[Random]
}
Run Code Online (Sandbox Code Playgroud)
val res = Random("a","b", 1, Data("e"))
当我做res.asJson.toString 时,我得到:
{
"a": "a",
"b": "b",
"c":1,
"d":
{
"e": "e"
}
}
但我希望它在没有 \n 的情况下打印在一行中,就像使用 circe 一样。
**{"a": "a","b": "b", "c": 1,d:{"e": "e"}}**
如果您期望收到类型A或类型B( Either[A, B]) 的 Json,您如何为其编写解码器?
例如,假设您正在为外部 API 构建一个客户端,该客户端可以使用一些预期的 Json 结构进行应答:
{
"fieldA": "value",
"fieldB": "value2"
}
Run Code Online (Sandbox Code Playgroud)
或者如果出现问题,它将使用带有字段的对象进行响应error:
{
"error": "Your request was wrong"
}
Run Code Online (Sandbox Code Playgroud)
然后你想要一个具有这些结构之一的实例:
{
"fieldA": "value",
"fieldB": "value2"
}
Run Code Online (Sandbox Code Playgroud)
如何为一种响应结构或另一种响应结构编写解码器?
我使用一些 Rest API 响应包含一种“混合”字段的 json。混合我的意思是它可以采用不同类型的值。在我的情况下Object,String并且Int是允许的。在Object本身由1Int和1 String。
我需要解码的对象如下所示:
一世
{
field1: 32,
...
value: {
id: 23,
text: "text"
}
}
Run Code Online (Sandbox Code Playgroud)
二
{
field1: 32,
...
value: 21
}
Run Code Online (Sandbox Code Playgroud)
三
{
field1: 32,
...
value: "value"
}
Run Code Online (Sandbox Code Playgroud)
如何处理circe中的此类对象?