2025年circe Encoding和Decoding

circe Encoding和DecodingEncoder A 是将 A 类型转化成 JSON 的函数 Decoder A 是将 Json 转化成一个 A 对象或者是 exception 的函数 circe 提供了 scala 标准库中类型的的 implicit 函数 可以方便的对 String Int 等基本类型进行处理 同时也提供了 List A Option A 和其他泛型类型

大家好,我是讯享网,很高兴认识大家。

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@fb

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@bc 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))

 

小讯
上一篇 2025-01-18 19:41
下一篇 2025-04-10 07:37

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/39103.html