Skip to content

Sealed trait member with own codec #463

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
shmishleniy opened this issue Jan 24, 2020 · 2 comments
Closed

Sealed trait member with own codec #463

shmishleniy opened this issue Jan 24, 2020 · 2 comments
Labels

Comments

@shmishleniy
Copy link

Hi,

import com.github.plokhotnyuk.jsoniter_scala.core._
import com.github.plokhotnyuk.jsoniter_scala.macros._
import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers

sealed trait BatchSource
case class Mother(tag: String) extends BatchSource
case class Package(id: String, tag: String) extends BatchSource

class CodecSpec extends AnyFunSpec  {
  implicit val codecMother: JsonValueCodec[Mother] = JsonCodecMaker.make[Mother](CodecMakerConfig.withDiscriminatorFieldName(Some("source")).withFieldNameMapper{
    case "tag" => "tag_id"
  })
  implicit val codecPackage: JsonValueCodec[Package] = JsonCodecMaker.make[Package](CodecMakerConfig.withDiscriminatorFieldName(Some("source")).withFieldNameMapper{
    case "tag" => "tag_id"
  })
  implicit val codecBatchSource: JsonValueCodec[BatchSource] = JsonCodecMaker.make[BatchSource](CodecMakerConfig.withDiscriminatorFieldName(Some("source")))

  it("codec") {
    val b = Package(id="17ebf4294-59ca-45a9-a6b7-373c2aa890fa", tag="ASDZXC123123")
    assert(writeToString[Package](b)     === """{"id":"17ebf4294-59ca-45a9-a6b7-373c2aa890fa","tag_id":"ASDZXC123123"}""")
    assert(writeToString[BatchSource](b) === """"{source":"Package","id":"17ebf4294-59ca-45a9-a6b7-373c2aa890fa","tag_id":"ASDZXC123123"}""")
  }
}

in case we encode by trait writeToString[BatchSource]
expected:
{source":"Package","id":"17ebf4294-59ca-45a9-a6b7-373c2aa890fa","tag_id":"ASDZXC123123"}
actual:
{"id":"17ebf4294-59ca-45a9-a6b7-373c2aa890fa","tag_id":"ASDZXC123123"}

seem trait codec codecBatchSource just using codecPackage without discriminator field.

as you can see I explicitly tried .withDiscriminatorFieldName(Some("source")) in codecPackage

@plokhotnyuk
Copy link
Owner

plokhotnyuk commented Jan 24, 2020

Hi, Andrii!

Thanks for trying and raising a question.

As for me, derivation of codecs works quite logically - if you want to store a product type (not a sum type or an enum) then the discriminator (or a type tag) is redundant.

The problem here that implicit values for codecMother and codecPackage are not isolated in the separated scope and override derivation of codecs for corresponding types in the JsonCodecMaker.make[BatchSource] call.

Below is an example of how derivation and declaration of implicit values can be isolated to meet your expectations:

object Codecs {
  val codecBatchSource: JsonValueCodec[BatchSource] = JsonCodecMaker.make[BatchSource](CodecMakerConfig.withDiscriminatorFieldName(Some("source")).withFieldNameMapper{
    case "tag" => "tag_id"
  })
  val codecPackage: JsonValueCodec[Package] = JsonCodecMaker.make[Package](CodecMakerConfig.withDiscriminatorFieldName(Some("source")).withFieldNameMapper{
    case "tag" => "tag_id"
  })
}

object ImplicitCodecs {
  implicit val codecBatchSource: JsonValueCodec[BatchSource] = Codecs.codecBatchSource
  implicit val codecPackage: JsonValueCodec[Package] = Codecs.codecPackage
}
  
import ImplicitCodecs._

@shmishleniy
Copy link
Author

So in case I need tag field mapping only for package but not for mother I should provide custom codec for sealed trait

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants