Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Sep 17 20:39
    codecov-io commented #1263
  • Sep 17 20:38
    codecov-io commented #1263
  • Sep 17 20:02
    scala-steward opened #1263
  • Sep 17 20:02
    scala-steward review_requested #1263
  • Sep 17 13:10
    alexandru edited #1262
  • Sep 17 13:09
    alexandru opened #1262
  • Sep 17 06:30

    travisbrown on master

    Update refined, refined-scalach… (compare)

  • Sep 17 06:30
    travisbrown closed #1261
  • Sep 17 00:45
    codecov-io commented #1261
  • Sep 17 00:43
    codecov-io commented #1261
  • Sep 17 00:29
    scala-steward opened #1261
  • Sep 17 00:29
    scala-steward review_requested #1261
  • Sep 16 13:36
    codecov-io commented #1260
  • Sep 16 13:34
    codecov-io commented #1260
  • Sep 16 13:20
    scala-steward opened #1260
  • Sep 16 13:20
    scala-steward review_requested #1260
  • Sep 16 03:25
    scala-steward review_requested #1259
  • Sep 16 03:25
    scala-steward opened #1259
  • Sep 15 08:25
    travisbrown commented #1257
  • Sep 15 07:42
    codecov-io commented #1257
Travis Brown
@travisbrown
@drewboardman that would work as well. unfortunately we have two implementations of derivation for case class instances…
circe-generic is the older, more mature, more principled version, but it can result in slow compile times.
for the most common usage style (deriveDecoder and deriveEncoder) they do exactly the same thing.

in your case you'd write:

implicit val decodeThing: Decoder[Thing] = deriveDecoder

with one of the following imports:

import io.circe.generic.semiauto.deriveDecoder
import io.circe.derivation.deriveDecoder
I'd probably recommend starting with circe-derivation
Travis Brown
@travisbrown
(but it really depends on how you value stability vs. keeping down compilation time)
Andriy Plokhotnyuk
@plokhotnyuk

I'd probably recommend starting with circe-derivation

is it a general recommendation or for that specific case? have circe-derivation a feature parity with circe-generic to be used as a drop-down replacement?

Travis Brown
@travisbrown
@plokhotnyuk circe-derivation doesn't support fully-automatic derivation (io.circe.generic.auto) at all, and never will.
Andriy Plokhotnyuk
@plokhotnyuk
why?
Travis Brown
@travisbrown
it adds a lot of complexity
to do it right you need some kind of fancy prioritization trick, since you don't want derived instances to override explicitly defined instances.
caching instances is tricky (and circe-generic doesn't do it), which means it's really easy to blow up compile times.
Andriy Plokhotnyuk
@plokhotnyuk
jsoniter-scala does full-auto derivation and is able to override custom codecs from the implicit definitions using the following routine with a cache of resolved codecs under-hood: https://github.com/plokhotnyuk/jsoniter-scala/blob/master/jsoniter-scala-macros/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodecMaker.scala#L322
Travis Brown
@travisbrown
I just don't think it's worth it. If someone wanted to contribute caching like that to circe-generic I'd consider it, but tbh I doubt it would be accepted…
how do you handle the "imports smash everything" problem?
Andriy Plokhotnyuk
@plokhotnyuk
could you, please, elaborate what a kind of problem it is? I think that some examples would help me understand that
Travis Brown
@travisbrown

sorry, just meant the issue that if a user has

case case Foo(x: String)

object Foo {
  implicit val decodeFoo: Decoder[Foo] = // custom instance here
}

case class Bar(y: Int, foo: Foo)

and they want to use fully-automatic derivation for Bar, any straightforward solution will result in the custom instance for Foo being ignored.

circe-generic gets around this with its own miniature version of the export-hook solution (which requires a macro on the generic instance definition side)
Andriy Plokhotnyuk
@plokhotnyuk
this case works for jsoniter-scala properly, just look and play with a test for the following data structure declaration: https://github.com/plokhotnyuk/jsoniter-scala/blob/master/jsoniter-scala-macros/src/test/scala/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodecMakerSpec.scala#L1886-L1906
Travis Brown
@travisbrown
Will take a look, thanks.
matfournier
@matfournier
Does anyone have a simple gist kicking around of deriving encoders/decoders when using the Refined library? I can only find an encoding example in the docstring here: https://github.com/circe/circe/blob/master/modules/refined/shared/src/main/scala/io/circe/refined/package.scala
truongio
@truongio

@truongio just wrote this up: https://stackoverflow.com/a/57919949/334519

Sorry, I forgot about this. Thank you so much @travisbrown! It worked great.

matfournier
@matfournier
I have to do some boilerplate to get refined decoders to work. Hopefully I'm missing some easier syntax? E.g. for the non empty string name field of some User case class val name = hc.downField("name").as[String].flatMap(s => refineV[NonEmpty](s).leftMap(m => DecodingFailure(m, List()))) I can't seem to get any easier syntax to work (e.g. semi-automatic decoders).
Travis Brown
@travisbrown
@matfournier can you give a complete example? it should just work
scala> import eu.timepit.refined._, api.Refined, numeric.Positive
import eu.timepit.refined._
import api.Refined
import numeric.Positive

scala> import io.circe.generic.semiauto._, io.circe.refined._
import io.circe.generic.semiauto._
import io.circe.refined._

scala> case class Foo(x: Refined[Int, Positive])
defined class Foo

scala> implicit val decodeFoo: io.circe.Decoder[Foo] = deriveDecoder
decodeFoo: io.circe.Decoder[Foo] = io.circe.generic.decoding.DerivedDecoder$$anon$1@65c53a66

scala> io.circe.jawn.decode[Foo]("""{"x": 1}""")
res0: Either[io.circe.Error,Foo] = Right(Foo(1))

scala> io.circe.jawn.decode[Foo]("""{"x": 0}""")
res1: Either[io.circe.Error,Foo] = Left(DecodingFailure(Predicate failed: (0 > 0)., List(DownField(x))))
matfournier
@matfournier
@travisbrown I did see the import of io.circe.refined._ in a few examples but oddly it's not a module in my install (using circe 0.11.1) . E..g import io.circe.refined._ says that refined isn't a package.
Facepalm. I know what my problem is. I forgot to add circe-refined to my deps in build.sbt. All good here folks, just me being an idiot.
Thank you for that example though. Now that I've fixed my build.sbt, it's all working as expected.
Leif Warner
@LeifW
Was circe-derivation recommended over generic-extras?
Christof Nolle
@nolledge
Hi I am currentlly moving from circe-generic to circe-derivation. As I was replacing my decoders/encoders. I now get a DecodingFailure and cant figure out what it means:
DecodingFailure(C[A], List(.... Is somebody familiar with this error?
Travis Brown
@travisbrown
@LeifW that's my informal personal recommendation.
Travis Brown
@travisbrown
@nolledge that's a failure when decoding a sequence of some kind. if you can share more info I'd be happy to take a look.
Christof Nolle
@nolledge
Thank you @travisbrown I am trying to parse something with a null value (for a field defined a Seq[String]) to a case class with a default value. I expected the case class to be constructed with the default value in this case, instead it results in this error.
Travis Brown
@travisbrown
@nolledge got it. Can you open an issue against circe-derivation? Any behavior like that that doesn't match circe-generic-extras should be considered a bug in my view.
Alberto Paro
@aparo
@nolledge you should clean from null first, your json and then decode it.
In case of circe-derivation pay attention that all your fields are circe serializable.
are you using special typeclassing? otherwise I suggest you to use @JsonCodec annotation to generate your codecs
Andriy Plokhotnyuk
@plokhotnyuk
Is it possible to print code that is generated for decoders/encoders during derivation?
Andriy Plokhotnyuk
@plokhotnyuk
It can be easy implemented as an optional printing of a message with prettified code to the compiler output before returning of the result expression from macros like here
Andriy Plokhotnyuk
@plokhotnyuk
It will help not only resolve issues, but also to use generated code as an example or the initial implementation before customization manually...
Christof Nolle
@nolledge
@travisbrown I created an issue with a small example. @aparo thats what I am currently doing. I use for most of my case classes the annotation. For the one which causes the error I clean the null values like this: implicit val myDecoder: Decoder[MyData] = deriveDecoder.prepare(_.withFocus(_.dropNullValues))but thats more of a workaround..
Travis Brown
@travisbrown
thanks, will take a look asap (probably tonight)
Drew Boardman
@drewboardman
I'm having some issues getting my decoder to compile for an enumeratum enum
import enumeratum.values.{ StringEnum, StringEnumEntry }
import io.circe._

import scala.collection.immutable

sealed abstract class MyThing(val value: String, val name: String) extends StringEnumEntry

case object MyThing extends StringEnum[MyThing] {

  case object Foo extends MyThing(value = "123", name = "some token")
  case object Bar extends MyThing(value = "456", name = "some other token")

  val values: immutable.IndexedSeq[MyThing] = findValues
}

object MyThingCodecs {
  implicit val encode: Encoder[MyThing] = new Encoder[MyThing] {
    final def apply(l: MyThing): Json = Json.fromString(l.name)
  }

  implicit val decode: Decoder[MyThing] = new Decoder[MyThing] {
    final def apply(c: HCursor): Decoder.Result[MyThing] =
      for {
        name <- c.downField("name").as[String]
      } yield
        MyThing
          .withValueOpt(name)
          .map(x => Right(x))
          .getOrElse(Left(DecodingFailure("Unable to parse into MyThing", List.empty)))
  }
}
from the circe library it looks like Result[A] is a type alias for an Either[DecodingFailure, A]
which I've provided, however it still is saying exprected Decoder.Result got Either
is there a simpler way to handle this decoding?
also should I be using c.history for the List[CursorOps]?
Drew Boardman
@drewboardman
This message was deleted
Drew Boardman
@drewboardman
This message was deleted
Drew Boardman
@drewboardman
figured it out
  implicit val decode: Decoder[MyThing] = new Decoder[MyThing] {
    final def apply(c: HCursor): Decoder.Result[MyThing] =
      c.downField("value")
        .as[String]
        .flatMap { foo =>
          MyThing.withValueOpt(foo) match {
            case Some(f) => Right(f)
            case None    => Left(DecodingFailure("error", c.history))
          }
        }
  }
chris vale
@crispywalrus
@travisbrown I was through circe-derivation and I noticed that while the readme says it’s not at feature parity due to not supporting ADT’s the merging of circe-derivation/#100 suggests that message is out of date. So is circe-derivation at feature parity with circe-generic?