Skip to content

Latest commit

 

History

History
154 lines (97 loc) · 3.98 KB

README.md

File metadata and controls

154 lines (97 loc) · 3.98 KB

e-circe

This is a Json codec implementation for E and EOr types based on circe. It provides circe's Decoders and Encoders as well as e's own Codec (see e-scala docs).

Installation

If you use SBT, add following to your build.sbt:

libraryDependencies += "dev.akif" %% "e-circe" % "@VERSION@"

If you use Maven, add following to your pom.xml:

<dependencies>
    <dependency>
        <groupId>dev.akif</groupId>
        <artifactId>e-circe_3</artifactId>
        <version>@VERSION@</version>
    </dependency>
</dependencies>

If you use Gradle, add following to your project's build.gradle:

dependencies
{
    implementation('dev.akif:e-circe_3:@VERSION@')
}

Contents

Below are some details and examples of e-circe's content. For more, please check corresponding automated tests and e-circe's documentation.

To get started, add following import which will cover all your needs:

import e.circe.{*, given}

1. Decoding

e-circe provides implicit definitions so that regular circe decoding can be done. However, it also provides e's own Codec. Using this is convenient as it reports decoding failures as E errors.

1.1. Decoding a Value

import e.circe.{*, given}
import io.circe.{Decoder => CirceDecoder, Encoder => CirceEncoder, Json}
import io.circe.syntax.*

decode[String](123.asJson)

decode[String]("test".asJson)

case class Foo(bar: Boolean)

given fooDecoder: CirceDecoder[Foo] = CirceDecoder.forProduct1("bar")(Foo.apply)

given fooEncoder: CirceEncoder[Foo] = CirceEncoder.forProduct1("bar")(_.bar)

decode[Foo](Json.obj())

decode[Foo](Foo(false).asJson)

1.2. Decoding an E

Decoding a Json as E yields EOr[E] whose error is the decoding failure. If the decoding succeeds, the provided value is the decoded E.

import e.circe.{*, given}
import e.scala.E
import io.circe.Json
import io.circe.syntax.*

// Decodes as `E.empty`
decode[E](Json.obj())

// Decoding failure, also an E
decode[E](Json.arr())

val decoder = makeDecoder[E]

decoder.decode(Json.obj("code" := 1, "name" := "test"))

2. Encoding

e-circe provides implicit definitions so that regular circe encoding can be done. It also provides e's own Codec and encoding can be done with it too.

2.1. Encoding an E

import e.circe.{*, given}
import e.scala.E

encode(E.empty)

encode(E.name("test").message("Test").cause(E.code(1)))

val encoder = makeEncoder[E]

encoder.encode(E.code(2))

2.2. Encoding an EOr

import e.circe.{*, given}
import e.scala.*

encode[EOr[String]](E.name("test").toEOr[String])

encode[EOr[Int]](123.toEOr)

val encoder = makeEncoder[EOr[String]]

encoder.encode(E.name("test").toEOr[String])

encoder.encode("123".toEOr)

3. Codec

Since e's Codec is a combination of decoding and encoding, you can use makeCodec instead of separately using makeDecoder and makeEncoder if you have both capabilities for a type.

import e.circe.{*, given}
import e.scala.*
import io.circe.{Decoder => CirceDecoder, Encoder => CirceEncoder, Json}
import io.circe.syntax.*

case class User(name: String, age: Int)

object User:
    given userDecoder: CirceDecoder[User] = CirceDecoder.forProduct2("n", "a")(User.apply)

    given userEncoder: CirceEncoder[User] = CirceEncoder.forProduct2("n", "a")(u => (u.name, u.age))

val codec = makeCodec[User]

codec.decode(Json.obj("foo" := "bar"))

codec.decode(Json.obj("n" := "Akif", "a" := 29))

codec.encode(User("Akif", 29))