Skip to content
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

How to completely disable discriminators #1103

Open
ColOfAbRiX opened this issue Dec 26, 2023 · 4 comments
Open

How to completely disable discriminators #1103

ColOfAbRiX opened this issue Dec 26, 2023 · 4 comments
Labels

Comments

@ColOfAbRiX
Copy link

ColOfAbRiX commented Dec 26, 2023

I'm writing a client in Scala 3 for a database that uses rest endpoints and I want to represent the requests internally using case classes which also include sealed traits/enum:

enum ServiceRequests:
  case RequestA(field1: String, field2: Int, ...) extends ServiceRequests

Because I'm interfacing with an existing service I cannot include any discriminator in the output json but I couldn't find how to. The only output I get is with a type field { "type": "RequestA", "field1": "...", "field2": "..." } or wrapped in another json object { "RequestA": { "field1": "...", "field2": "..." } } and none of these options are acceptable.

I couldn't find if this is possible and how to do it.

@plokhotnyuk
Copy link
Owner

plokhotnyuk commented Dec 27, 2023

@ColOfAbRiX Hi, Fabrizio!

Thanks for the question!

Unfortunately, there no simple direct solution for derivation of such codecs.

For your case there is a couple of workaround options:

  • use additional data structures that match JSON more closely and then convert between them and your existing data structures using chimney or ducktape libraries
  • derive codecs for concrete request classes, like val requestACodec = JsonCodecMaker.make[ServiceRequests.RequestA] and write your own custom codec to determine which of them should be used for parsing of incoming requests

I will be happy to help you in writing of some acceptable solution based on concrete JSON samples and data structures.

@ColOfAbRiX
Copy link
Author

Thanks, probably the second of your suggestions feels the most appropriate, as I'm already working with the closest data structure to the api

@plokhotnyuk
Copy link
Owner

plokhotnyuk commented Dec 27, 2023

Also, to avoid XY problem, please give some context to understand why just using codecs for concrete case classes is not enough for your case? Why do you need extending of ServiceRequests for all of them and use a codec for abstract ServiceRequests instead?

As example, usually doing REST we use different paths for different types of requests, so corresponding concrete class codecs could be easily pattern matched by paths, no need for generic one for an abstract class...

@DavidPerezIngeniero
Copy link

You can use:

given JsonValueCodec[MyClass] = make(CodecMakerConfig.withDiscriminatorFieldName(None))

Example:

#!/usr/bin/env -S scala-cli -j system -J -Xmx2g

//> using dep com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-core:2.31.1
//> using dep com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-macros:2.31.1

import com.github.plokhotnyuk.jsoniter_scala.core.*
import com.github.plokhotnyuk.jsoniter_scala.macros.*

sealed trait Base
case class A(a1: Int, a2: Int) extends Base
case class B(b1: Int, b2: Int) extends Base

given CodecMakerConfig.PrintCodec with {}

given JsonValueCodec[Seq[Base]] = JsonCodecMaker.make(CodecMakerConfig.withDiscriminatorFieldName(None))
val json =  writeToString(Seq(A(1,2),B(3,4)))
println(json)
println(readFromString[Seq[Base]](json))

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

3 participants