Skip to content

Commit

Permalink
Circe KeyEncoder/KeyDecoder for Enum (lloydmeta#219)
Browse files Browse the repository at this point in the history
  • Loading branch information
yaroot authored and lloydmeta committed Mar 21, 2019
1 parent 117776a commit a85a867
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 3 deletions.
13 changes: 12 additions & 1 deletion enumeratum-circe/src/main/scala/enumeratum/Circe.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package enumeratum

import cats.syntax.either._
import io.circe.Decoder.Result
import io.circe.{Encoder, Decoder, Json, HCursor, DecodingFailure}
import io.circe.{Encoder, Decoder, Json, HCursor, DecodingFailure, KeyEncoder, KeyDecoder}

/**
* Created by Lloyd on 4/14/16.
Expand Down Expand Up @@ -80,6 +80,17 @@ object Circe {
}
}

/**
* Returns a KeyEncoder for the given enum
*/
def keyEncoder[A <: EnumEntry](enum: Enum[A]): KeyEncoder[A] = KeyEncoder.instance(_.entryName)

/**
* Returns a KeyDecoder for the given enum
*/
def keyDecoder[A <: EnumEntry](enum: Enum[A]): KeyDecoder[A] =
KeyDecoder.instance(enum.withNameOption)

private val stringEncoder = implicitly[Encoder[String]]
private val stringDecoder = implicitly[Decoder[String]]

Expand Down
10 changes: 10 additions & 0 deletions enumeratum-circe/src/main/scala/enumeratum/CirceKeyEnum.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package enumeratum
import io.circe.{KeyEncoder, KeyDecoder}

/**
* Helper trait that adds implicit Circe KeyEncoder/KeyDecoder for an [[Enum]]'s members.
*/
trait CirceKeyEnum[A <: EnumEntry] { this: Enum[A] =>
implicit val circeKeyEncoder: KeyEncoder[A] = Circe.keyEncoder(this)
implicit val circeKeyDecoder: KeyDecoder[A] = Circe.keyDecoder(this)
}
28 changes: 28 additions & 0 deletions enumeratum-circe/src/test/scala/enumeratum/CirceKeySpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package enumeratum

import org.scalatest.{FunSpec, Matchers}
import cats.syntax.either._
import io.circe.Json
import io.circe.syntax._

class CirceKeySpec extends FunSpec with Matchers {
describe("to JSON") {
it("should work") {
Map(ShirtSize.Small -> 5, ShirtSize.Large -> 10).asJson shouldBe Json.obj(
"Small" -> 5.asJson,
"Large" -> 10.asJson
)
}
}

describe("from JSON") {
it("should work") {
Json
.obj(
"Medium" -> 100.asJson,
"Large" -> 15.asJson
)
.as[Map[ShirtSize, Int]] shouldBe Map(ShirtSize.Medium -> 100, ShirtSize.Large -> 15).asRight
}
}
}
7 changes: 5 additions & 2 deletions enumeratum-circe/src/test/scala/enumeratum/ShirtSize.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ package enumeratum
*
* Copyright 2016
*/
sealed trait ShirtSize extends EnumEntry
sealed trait ShirtSize extends EnumEntry with Product with Serializable

case object ShirtSize extends CirceEnum[ShirtSize] with Enum[ShirtSize] {
case object ShirtSize
extends CirceEnum[ShirtSize]
with CirceKeyEnum[ShirtSize]
with Enum[ShirtSize] {

case object Small extends ShirtSize
case object Medium extends ShirtSize
Expand Down

0 comments on commit a85a867

Please sign in to comment.