`

circe Encoding和Decoding

 
阅读更多

Encoder[A]是将A类型转化成JSON的函数,Decoder[A]是将Json转化成一个A对象或者是exception的函数。

 

circe提供了scala标准库中类型的的implicit函数,可以方便的对String,Int等基本类型进行处理,同时也提供了List[A]、Option[A]和其他泛型类型的处理,只要是A有对应的Encoder。

 

可以使用 .asJson 将一个数据对象转化成Json对象:

import io.circe.syntax._
// import io.circe.syntax._

val intsJson = List(1, 2, 3).asJson
// intsJson: io.circe.Json =
// [
//   1,
//   2,
//   3
// ]

 使用 .as 将一个Json对象转化成数据对象:

intsJson.as[List[Int]]
// res0: io.circe.Decoder.Result[List[Int]] = Right(List(1, 2, 3))

parser模块中的decode函数可以直接把json string转化成对象:

import io.circe.parser.decode
// import io.circe.parser.decode

decode[List[Int]]("[1, 2, 3]")
// res1: Either[io.circe.Error,List[Int]] = Right(List(1, 2, 3))

Semi-automatic Derivation

有时,在代码中定义一个Encoder或Encoder,半自动推导可以帮助更简单的实现,可以写成如下形式:

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

case class Foo(a: Int, b: String, c: Boolean)

implicit val fooDecoder: Decoder[Foo] = deriveDecoder[Foo]
implicit val fooEncoder: Encoder[Foo] = deriveEncoder[Foo]

 或者是:

implicit val fooDecoder: Decoder[Foo] = deriveDecoder
implicit val fooEncoder: Encoder[Foo] = deriveEncoder

@JsonCodec

circe-generic模块提供了@JsonCodec注解用来简化上面的实现:

import io.circe.generic.JsonCodec, io.circe.syntax._
// import io.circe.generic.JsonCodec
// import io.circe.syntax._

@JsonCodec case class Bar(i: Int, s: String)
// defined class Bar
// defined object Bar

Bar(13, "Qux").asJson
// res4: io.circe.Json =
// {
//   "i" : 13,
//   "s" : "Qux"
// }

 这种注解方式对case classes和sealed trait有效。

注意: 你需要使用Macro Paradise插件用来调用了类似 @JsonCodec的注解

forProductN 方法

也可以在不使用通用derviation的情况下构建case class的Encoders和Decoders:

case class User(id: Long, firstName: String, lastName: String)

object UserCodec {
  implicit val decodeUser: Decoder[User] =
    Decoder.forProduct3("id", "first_name", "last_name")(User.apply)

  implicit val encodeUser: Encoder[User] =
    Encoder.forProduct3("id", "first_name", "last_name")(u =>
      (u.id, u.firstName, u.lastName)
    )
}

 这种方式不如generic derivation通用,但这种方式只依赖于circe-core

Fully automatic derivation

circe使用shapeless实现自动的推导对应的class实例:

import io.circe.generic.auto._
// import io.circe.generic.auto._

case class Person(name: String)
// defined class Person

case class Greeting(salutation: String, person: Person, exclamationMarks: Int)
// defined class Greeting

Greeting("Hey", Person("Chris"), 3).asJson
// res6: io.circe.Json =
// {
//   "salutation" : "Hey",
//   "person" : {
//     "name" : "Chris"
//   },
//   "exclamationMarks" : 3
// }

Custom encoders/decoders

如果你想自己实现而不是使用自动化或半自动化的derivation,可以通过一下几种方法实现:

首先,可以从头编写一个Encoder[A]和Decoder[A]:

class Thing()
// defined class Thing

implicit val encodeFoo: Encoder[Thing] = new Encoder[Thing] {
  final def apply(a: Thing): Json = ??? // your implementation goes here
}
// encodeFoo: io.circe.Encoder[Thing] = $anon$1@4ef154df

implicit val decodeFoo: Decoder[Thing] = new Decoder[Thing] {
  final def apply(c: HCursor): Decoder.Result[Thing] = Left(DecodingFailure("Not implemented yet", c.history))
}
// decodeFoo: io.circe.Decoder[Thing] = $anon$1@164a929d

 但在许多情况下,您可能会发现它更方便搭载已经可用的Decoder。例如,java.time.Instance 的解码器可以这样写:

import cats.syntax.either._
// import cats.syntax.either._

import java.time.Instant
// import java.time.Instant

implicit val encodeInstant: Encoder[Instant] = Encoder.encodeString.contramap[Instant](_.toString)
// encodeInstant: io.circe.Encoder[java.time.Instant] = io.circe.Encoder$$anon$11@56e2186a

implicit val decodeInstant: Decoder[Instant] = Decoder.decodeString.emap { str =>
  Either.catchNonFatal(Instant.parse(str)).leftMap(t => "Instant")
}
// decodeInstant: io.circe.Decoder[java.time.Instant] = io.circe.Decoder$$anon$21@419672fb

Custom key types

如果需要对Map [K,V]进行编码/解码,其中K不是String(或Symbol,Int,Long等),则需要为自定义键类型提供KeyEncoder和/或KeyDecoder。

import io.circe.syntax._
// import io.circe.syntax._

case class Foo(value: String)
// defined class Foo

implicit val fooKeyEncoder = new KeyEncoder[Foo] {
  override def apply(foo: Foo): String = foo.value
}
// fooKeyEncoder: io.circe.KeyEncoder[Foo] = $anon$1@423285bc

val map = Map[Foo, Int](
  Foo("hello") -> 123,
  Foo("world") -> 456
)
// map: scala.collection.immutable.Map[Foo,Int] = Map(Foo(hello) -> 123, Foo(world) -> 456)

val json = map.asJson
// json: io.circe.Json =
// {
//   "hello" : 123,
//   "world" : 456
// }

implicit val fooKeyDecoder = new KeyDecoder[Foo] {
  override def apply(key: String): Option[Foo] = Some(Foo(key))
}
// fooKeyDecoder: io.circe.KeyDecoder[Foo] = $anon$1@7edf5d5a

json.as[Map[Foo, Int]]
// res7: io.circe.Decoder.Result[Map[Foo,Int]] = Right(Map(Foo(hello) -> 123, Foo(world) -> 456))

 

分享到:
评论

相关推荐

    circe, 在Emacs中,Circe的客户端.zip

    circe, 在Emacs中,Circe的客户端 Circe,Emacs中的IRC客户端 概述 Circe是Emacs中IRC的客户端。 它尝试使用正确的默认值,并与编辑器的它的余部分合并,使用标准的Emacs密钥绑定。复杂性,它是介于 rcirc ( 极小) ...

    circe-yaml:使用SnakeYAML进行圈划的YAML解析器

    `circe-yaml`是一个基于Scala的库,它结合了circe和SnakeYAML两个强大的工具,为开发者提供了一个高效且灵活的YAML解析和序列化解决方案。circe是一个JSON库,而SnakeYAML则是Java的YAML 1.1处理器。通过`circe-yaml...

    circe-json-schema:Circe的JSON模式验证

    circe-json-schema 该项目提供了一些基本的工具,可以使用执行验证。 该库的当前版本是的包装,尽管它未在其公共API中公开任何org.everit或org.json类型。 将来的版本将删除Everit依赖性,尽管我们目前尚无确切的...

    circe-circus:基于Circe的微型库

    circe-circus是一个专注于Circe库的轻量级扩展库,旨在提供更便捷的数据编码、解码和序列化功能,以增强Scala开发者在处理JSON数据时的体验。Circe本身是一个强大的JSON库,它采用了函数式编程的思路,使得在Scala中...

    circe-magnolia:使用木兰的circe编解码器派生

    3. 使用circe-magnolia提供的宏,如`io.circe.generic.magnolia.semiauto.deriveDecoder`和`io.circe.generic.magnolia.semiauto.deriveEncoder`,来自动生成`User`的解码器和编码器。 4. 在需要解析或序列化JSON的...

    scalapb-circe:用于ScalaPB的JsonProtobuf转换器大约

    头皮回旋 该项目的结构受到极大启发相依性包含在您的build.sbt文件中核libraryDependencies + = " io.github.scalapb-json " %% " scalapb-circe " % " 0.10.0 " 对于scala-js libraryDependencies + = " io.github....

    circe-deriving:Circe的快速类型类实例派生

    在Scala编程环境中,Circe是一个非常流行的JSON库,它提供了强大的编码和解码功能,使得处理JSON数据变得简单而高效。"circe-deriving"是Circe的一个扩展模块,专门用于自动派生JSON编码器和解码器,大大简化了类型...

    circe-schema:Circe 的 JSON 模式

    版权和许可circe-schema 根据 (“许可”)获得许可; 除非遵守许可,否则您不得使用本软件。 除非适用法律要求或以书面形式同意,否则根据“许可”分发的软件将按“原样”分发,没有任何明示或暗示的保证或条件。 ...

    circe:Circe,Emacs 中 IRC 的客户端

    在复杂性方面,它介于 rcirc(非常小)和 ERC(非常复杂)之间。 截屏 安装 依赖关系 为了使用 TLS 安全地连接到 IRC 服务器,Circe 需要一个与库链接的 Emacs。 为了显示图像,Circe 需要 。 package.el 确保您...

    circe-fs2:使用 fs2 流式传输 JSON 解析和解码

    该项目支持使用使用进行流式 JSON 解析和解码, 是一个用于将 JSON 编码和解码为 Scala 类型的 Scala 库。 解析 Circe-fs2 提供不同的管道来解析您的 JSON 流,具体取决于您的流是否为: \n 分隔的 JSON 值流或值...

    Circe Matis-开源

    同时,"sgn2gtx"可能包含的功能暗示了Circe Matis还支持对GPS数据的处理和转换,这对于现代GIS应用和导航系统尤其有用。通过这样的工具,用户可以更便捷地集成和分析地理位置数据,服务于各种专业应用,如城市规划、...

    醉酒:基于桑格利亚汽酒,Akka HTTP和Circe的简单GraphQL客户端

    再者,Circe是Scala中一个强大的JSON库,它提供了JSON序列化和反序列化的功能。在处理GraphQL查询结果时,Circe帮助我们将接收到的JSON数据转换为Scala对象,反之亦然。这使得我们能够方便地操作和处理来自GraphQL...

    simple-http4s-api:只是在Play Json和Circe之上使用“ http4s”和Json支持的简单API

    1. **自动解码和编码**: Circe提供了一种自动将Scala数据类型转换为JSON和从JSON反序列化的方法,通过`Derivation`模块可以自动生成解码器和编码器。 2. **类型安全**: 类型系统的使用确保了在编码和解码过程中不会...

    Circe-开源

    下载并解压这个文件后,用户将获得Circe的源代码和其他相关文件,可以编译和安装在自己的系统上使用或进行二次开发。 总的来说,Circe是一个使用Python和wxPython构建的开源IRC客户端,它提供了一个多平台的解决...

    todo-http4s-doobie:使用http4s,doobie和circe的微服务的示例项目

    `circe`是Scala的一个JSON库,它基于cats和shapeless,提供了编译时安全的JSON解析和生成。在微服务中,circe用于将数据模型转换为JSON格式,以便于在HTTP响应中发送,同时也能将接收到的JSON请求数据解码为内部的...

    org.jresearch.commons.gwt.utils.shared-1.0.45.zip

    circe的"core"模块包含了基本的JSON类型和操作,而其他模块如"circe-generic"和"circe-optics"则提供了更高级的功能,如自动编码/解码和使用Scala的 optics(如 monocle 或 cats-effect 的 optics)来操作JSON。...

    bottledynamo:Scala中使用Twitter Futures进行Circe JSON序列化的AWS DynamoDB抽象足够好

    在本文中,我们将深入探讨`bottledynamo`项目,这是一个专门为Scala开发的库,它利用Twitter Futures和Circe库来实现对AWS DynamoDB的高效、流畅的JSON序列化和操作。`bottledynamo`是针对无SQL数据库系统的持久层...

    circe-literal-extras

    文字文摘 编译时间文字json验证程序,支持基于类型架构的内联值。 Scala JSON库的额外模块。 受支持的Scala版本包括3.0.0-M3。... circe . literal . extras . _ extension ( inline sc : StringCont

Global site tag (gtag.js) - Google Analytics