在光滑中使用circe来获取json中的数据时,我可以获取(Timestamp/DateTime)实体中没有日期字段的数据.但是当我Timestamp在实体中使用字段时,会抛出错误:
[error] /var/www/html/scala-api/src/main/scala/oc/api/http/routes/TestApi.scala:40: could not find implicit value for parameter encoder: io.circe.Encoder[Seq[oc.api.models.UserEntity]]
[error] auth => complete(userDao.getAll().map(_.asJson))
Run Code Online (Sandbox Code Playgroud)
这是代码,我用于Slick Entities并使用CIRCE进行json编码.
BaseTable:
abstract class BaseTable[T](tag: Tag, name: String) extends Table[T](tag, name) {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def createdAt = column[Timestamp]("created_at")
def updatedAt = column[Timestamp]("updated_at")
def deletedAt = column[Timestamp]("deleted_at")
}
Run Code Online (Sandbox Code Playgroud)
BaseEntity:
trait BaseEntity {
val id : Long
def isValid : Boolean = true
}
Run Code Online (Sandbox Code Playgroud)
UserEntity:createdAt生成编码器错误
case class UserEntity(id: Long, email: String, password: String, createdAt: Timestamp) extends BaseEntity …Run Code Online (Sandbox Code Playgroud) 假设有以下json有效负载
val json = """{
"choices" : [
{
"name" : "A"
},
{
"name" : "B"
},
{
"name" : "C"
},
{
"name" : "D"
}
],
"domain" : "Quizz",
"level" : "Test",
"mandatory": true
}"""
Run Code Online (Sandbox Code Playgroud)
我该如何将其转换为
val json = """{
"value":"B",
"domain" : "Quizz",
"level" : "Test",
}"""
Run Code Online (Sandbox Code Playgroud)
从可用选项中随机选择"B"?
这是我到目前为止所得到的:
val cursor = parse(json).getOrElse(Json.Null).cursor
for{
noMandatory<- cursor.downField("mandatory").flatMap(_.delete).map(_.top)
withEmptyValue = noMandatory.deepMerge(Json.obj("value"->Json.Null))
}yield withEmptyValue
Run Code Online (Sandbox Code Playgroud)
这将删除未使用的"必需"字段并插入一个空的"值"字段.从数组中获取一个随机值并将其置于"值"中会让我感到惊讶.
- 编辑
我尝试过使用hcursor,这使得上面更清楚(无论如何)
val cursor = parse(json).getOrElse(Json.Null).hcursor
val noMandatory = cursor.downField("mandatory").delete
val withEmptyValue = …Run Code Online (Sandbox Code Playgroud) 假设我有以下需要使用circe序列化为JSON对象的case类:
@JsonCodec
case class A(a1: String, a2: Option[String])
@JsonCodec
case class B(b1: Option[A], b2: Option[A], b3: Int)
Run Code Online (Sandbox Code Playgroud)
现在我需要编码val b = B(None, Some(A("a", Some("aa")), 5)为JSON但我希望能够控制它是否输出为
{
"b1": null,
"b2": {
"a1": "a",
"a2": "aa"
},
"b3": 5
}
Run Code Online (Sandbox Code Playgroud)
要么
{
"b2": {
"a1": "a",
"a2": "aa"
},
"b3": 5
}
Run Code Online (Sandbox Code Playgroud)
使用Printer's dropNullKeysconfig,例如,b.asJson.noSpaces.copy(dropNullKeys = true)将导致None从输出中省略s,而将其设置为false将Nones 编码为null(也参见此问题).但是如何在每个字段的基础上控制此设置?
鉴于以下ADT
sealed abstract class GroupRepository(val `type`: String) {
def name: String
def repositories: Seq[String]
def blobstore: String
}
case class DockerGroup(name: String, repositories: Seq[String], blobstore: String = "default") extends GroupRepository("docker")
case class BowerGroup(name: String, repositories: Seq[String], blobstore: String = "default") extends GroupRepository("bower")
case class MavenGroup(name: String, repositories: Seq[String], blobstore: String = "default") extends GroupRepository("maven")
Run Code Online (Sandbox Code Playgroud)
其中值type用于解码要实例化的实例.
如何自动(或半自动)派生编码器和解码器,我得到以下行为:
> println(MavenGroup("test", Seq("a", "b")).asJson.spaces2)
{
"type" : "maven",
"name" : "test",
"repositories" : [
"a",
"b"
],
"blobstore" : "default"
}
> …Run Code Online (Sandbox Code Playgroud) 可以说我有这个案例类:
case class Foo(bar: String, baz: Boolean = false)
在使用akka-http-json解码/编码API请求/响应时使用
在类似于此的示例中:
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives
import akka.stream.{ ActorMaterializer, Materializer }
import scala.io.StdIn
object ExampleApp {
private final case class Foo(bar: String, baz: Boolean = false)
def main(args: Array[String]): Unit = {
implicit val system = ActorSystem()
implicit val mat = ActorMaterializer()
Http().bindAndHandle(route, "127.0.0.1", 8000)
StdIn.readLine("Hit ENTER to exit")
system.terminate()
}
private def route(implicit mat: Materializer) = {
import Directives._
import FailFastCirceSupport._
import io.circe.generic.auto._
pathSingleSlash …Run Code Online (Sandbox Code Playgroud) 鉴于以下关于亚扪人:
@ import $ivy.`io.circe::circe-core:0.9.0`
@ import $ivy.`io.circe::circe-generic:0.9.0`
@ import $ivy.`com.chuusai::shapeless:2.3.3`
@ import shapeless.tag
import shapeless.tag
@ trait Foo
defined trait Foo
@ import io.circe._, io.circe.generic.semiauto._
import io.circe._, io.circe.generic.semiauto._
@ import shapeless.tag.@@
import shapeless.tag.@@
Run Code Online (Sandbox Code Playgroud)
然后,我尝试定义通用标记类型解码器:
@ implicit def taggedTypeDecoder[A, B](implicit ev: Decoder[A]): Decoder[A @@ B] =
ev.map(tag[B][A](_))
defined function taggedTypeDecoder
Run Code Online (Sandbox Code Playgroud)
它在明确拼写时有效String @@ Foo:
@ val x: String @@ Foo = tag[Foo][String]("foo")
x: String @@ Foo = "foo"
@ implicitly[Decoder[String @@ Foo]]
res10: Decoder[String @@ Foo] = io.circe.Decoder$$anon$21@2b17bb37
Run Code Online (Sandbox Code Playgroud)
但是,在定义类型别名时:
@ …Run Code Online (Sandbox Code Playgroud) 假设我一直在使用这样的JSON:
{ "id": 123, "name": "aubergine" }
Run Code Online (Sandbox Code Playgroud)
通过将其解码为Scala case类,如下所示:
{ "id": 123, "name": "aubergine" }
Run Code Online (Sandbox Code Playgroud)
这与circe的泛型推导工作得很好:
case class Item(id: Long, name: String)
Run Code Online (Sandbox Code Playgroud)
现在假设我要向表示形式添加本地化信息:
{ "id": 123, "name": { "localized": { "en_US": "eggplant" } } }
Run Code Online (Sandbox Code Playgroud)
我不能直接通过泛型派生使用这样的案例类:
scala> import io.circe.generic.auto._, io.circe.jawn.decode
import io.circe.generic.auto._
import io.circe.jawn.decode
scala> decode[Item]("""{ "id": 123, "name": "aubergine" }""")
res1: Either[io.circe.Error,Item] = Right(Item(123,aubergine))
Run Code Online (Sandbox Code Playgroud)
…因为语言标签是键,而不是字段。如何做到这一点,最好不要增加太多样板?
我可以很容易地为一个密封的案例类家族推导出一个编解码器,如下所示:
import io.circe._
import io.circe.generic.auto._
sealed trait Base
case class X(x: Int) extends Base
case class Y(y: Int) extends Base
object Test extends App {
val encoded = Encoder[Base].apply(Y(1))
val decoded = Decoder[Base].apply(encoded.hcursor)
println(decoded) // Right(Y(1))
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我将类型成员添加到基类中,我就不能再这样做了,即使它受到密封特性的限制:
import io.circe._
import io.circe.generic.auto._
sealed trait Inner
case class I1(i: Int) extends Inner
case class I2(s: String) extends Inner
sealed trait Base { type T <: Inner }
case class X[S <: Inner](x: S) extends Base { final type T = S …Run Code Online (Sandbox Code Playgroud) 我希望在我的案例类和 JSON 中拥有不同的字段名称,因此我需要一种舒适的方式来重命名编码和解码。
有人有好的解决方案吗?
我试图找到一种简单而有效的方法来使用 Scala 3 来(反)序列化枚举circe。
考虑以下示例:
import io.circe.generic.auto._
import io.circe.syntax._
enum OrderType:
case BUY
case SELL
case class Order(id: Int, `type`: OrderType, amount: String)
val order = Order(1, OrderType.SELL, "123.4")
order.asJson
Run Code Online (Sandbox Code Playgroud)
序列化数据后,它变成
{
"id" : 1,
"type" : {
"SELL" : {
}
},
"amount" : "123.4"
}
Run Code Online (Sandbox Code Playgroud)
代替
{
"id" : 1,
"type" : "SELL",
"amount" : "123.4"
}
Run Code Online (Sandbox Code Playgroud)
这就是我想要的。
我知道我可以为此编写一个自定义(反)序列化器,它将解决这个特定实例的问题,如下所示:
implicit val encodeOrderType: Encoder[OrderType] = (a: OrderType) =>
Encoder.encodeString(a.toString)
implicit def decodeOrderType: Decoder[OrderType] = (c: HCursor) => …Run Code Online (Sandbox Code Playgroud)