 may be more inclined to continue visiting stores in person, as these conveniences are simply not possible online. Allowing individuals to access machines on their own is also a smart way to reduce overhead costs for the business and employees can focus on other important issues affecting the customer experience. Creative problem solving is essential to staying on top of competition in the supermarket industry, and these low-cost tools are a smart choice for independent business owners.Q: How to serialize and deserialize traits, to and from Json, in Scala? First Attempt:
So far I have tried spray-json. I have:

trait Base

case class A ( id: String) extends Base

case class B (id: String) extends Base


Now, for serializing and deserializing my Base type, I have the code:
implicit object BaseFormat extends RootJsonFormat[Base]{
    def write(obj: Base): JsValue = {
      obj match {
        case a: A => a.toJson
        case b: B => b.toJson
        case unknown @ _ => serializationError(s"Marshalling issue with ${unknown}")
      }
    }

    def read(json: JsValue): Base = {
      //how to know whether json is encoding an A or a B?
    }
  }


The problem is that, for implementing the read method for deserialization, I can't figure out a way to know whether the JsValue is encoding an A or a B.
Second Attempt:
For solving this in spray-json, I ended up simply renaming the field id in A to aID, and in B to bID.
Third Attempt:
Since spray-json was not as sophisticated as the alternative libraries such as zio-json or circe, which handle this issue by themselves without additional code, I started using zio-json
Now I get the error
magnolia: could not infer DeriveJsonEncoder.Typeclass for type
for all the case classes taking type parameters.
Also, it has problems with chained trait inheritance. It seems like circe uses magnolia, too. So it’s likely this would be replicated with circe, as well.
Any help would be appreciated.

A: You should address this problem using a json encoding/decoding library.
Here is an example using circe and it's semi-automatic mode.
Since you mentionned in the comments that you are struggling with generic types in your case classes, I'm also including that. Basically, to derive an encoder or decoder for a class Foo[T] that contains a T, you have to prove that there is a way to encode and decode T. This is done by asking for an implicit Encoder[T] and Decoder[T] where you derive Encoder[Foo[T]] and Decoder[Foo[T]]. You can generalize this reasoning to work with more than one generic type of course, you just have to have an encoder/decoder pair implicitly available where you derive the encoder/decoder for the corresponding case class.
import io.circe._, io.circe.generic.semiauto._, io.circe.syntax._

case class Foo[T](a: Int, b: String, t: T)
object Foo {
  implicit def decoder[T: Encoder: Decoder]: Decoder[Foo[T]] = deriveDecoder
  implicit def encoder[T: Encoder: Decoder]: Encoder[Foo[T]] = deriveEncoder
}

case class Bar(a: Int)
object Bar {
  implicit val encoder: Encoder[Bar] = deriveEncoder
  implicit val decoder: Decoder[Bar] = deriveDecoder
}

case class Baz(a: Int)

println(Foo(42, "hello", 23.4).asJson) // Works because circe knows Encoder[Float] 
println(Foo(42, "hello", Bar(42)).asJson) // Works because we defined Encoder[Bar] 

//println(Foo(42, "hello", Baz(42)).asJson) // Doesn't compile: circe doesn't know Encoder[Baz] in semi-auto mode

Try it live on Scastie
Note that a different encoder/decoder for Foo[T] needs to be generated for each type T that you are using, which is why the encoder and decoder derivation for Foo have to be methods, not values like for Bar.
There is also a fully-automatic mode, but it tends to produce compile-time errors that are harder to debug for beginner, so I would start with semi-auto. Another problem, is that auto-mode can take much longer to compile on large projects. If you're feeling adventurous, it's even more beautiful when you don't make mistakes!
import io.circe._, io.circe.generic.auto._, io.circe.syntax._

case class Foo[T](a: Int, b: String, t: T)
case class Bar(a: Int)
case class Baz(a: Int)

println(Foo(42, "hello", 23.4).asJson) // circe knows Encoder[Float] and automatically derives Encoder[Foo[Float]]
println(Foo(42, "hello", Bar(42)).asJson) // circe wants Encoder[Foo[Bar]], so it ma(cro)gically derives Encoder[Bar] and then Encoder[Foo[Bar]]
println(Foo(42, "hello", Baz(42)).asJson) // Does compile this time, circe automatically find the encoder/decoder for Baz the same way it does for Bar

Try it live on Scastie

A: A working example using traits with generics is this:
import io.circe.Decoder.Result
import io.circe._
import io.circe.generic.semiauto._
import io.circe.syntax._


trait MyBase[T <: MyBase[T]] {
  def myid: String
  def issue: MyBaseIssue
  def summary: MyBaseSummary[T]
}

trait MyBaseIssue

object MyBaseIssue {
  implicit val decodeIssue: Decoder[MyBaseIssue] =
    Decoder[SimpleBaseIssue].map[MyBaseIssue](identity).or(
      Decoder[SophisticatedBaseIssue].map[MyBaseIssue](identity)
    )

  implicit val encodeIssue: Encoder[MyBaseIssue] = Encoder.instance {
    case simple @ SimpleBaseIssue(_) => simple.asJson
    case sophisticated @ SophisticatedBaseIssue(_) => sophisticated.asJson

  }
}

trait MyBaseSummary[T <: MyBase[T]]

object MyBaseSummary {
  implicit def decodeSummary[T <: MyBase[T]: Encoder: Decoder]
  : Decoder[MyBaseSummary[T]] =
    Decoder[SimpleBaseSummary].map[MyBaseSummary[SimpleBase]](identity).asInstanceOf[Decoder[MyBaseSummary[T]]].or(
      Decoder[SophisticatedBaseSummary].map[MyBaseSummary[SophisticatedBase]](identity).asInstanceOf[Decoder[MyBaseSummary[T]]]
    )


  implicit def encodeSummary[T <: MyBase[T]: Encoder: Decoder]
  : Encoder[MyBaseSummary[T]] = Encoder.instance {
    case simple @ SimpleBaseSummary(_) => simple.asJson
    case sophisticated @ SophisticatedBaseSummary(_) => sophisticated.asJson

  }
}

case class SimpleBase(
                       myid: String,
                       override val issue: SimpleBaseIssue,
                       override val summary: SimpleBaseSummary
                     ) extends MyBase[SimpleBase]

case class SophisticatedBase(
                              myid: String,
                              extraField: String,
                              override val issue: SophisticatedBaseIssue,
                              override val summary: SophisticatedBaseSummary
                            ) extends MyBase[SophisticatedBase]

object SimpleBase {
  implicit val encoder: Encoder[SimpleBase] = deriveEncoder
  implicit val decoder: Decoder[SimpleBase] = deriveDecoder
}

object SophisticatedBase {
  implicit val encoder: Encoder[SophisticatedBase] = deriveEncoder
  implicit val decoder: Decoder[SophisticatedBase] = deriveDecoder
}

case class SimpleBaseIssue(simpleIssueType: String) extends MyBaseIssue
case class SophisticatedBaseIssue(sophisticatedIssueType: String) extends MyBaseIssue

object SimpleBaseIssue {
  implicit val encoder: Encoder[SimpleBaseIssue] = deriveEncoder
  implicit val decoder: Decoder[SimpleBaseIssue] = deriveDecoder
}

object SophisticatedBaseIssue {
  implicit val encoder: Encoder[SophisticatedBaseIssue] = deriveEncoder
  implicit val decoder: Decoder[SophisticatedBaseIssue] = deriveDecoder
}

case class SimpleBaseSummary(simpleSummary: String) extends MyBaseSummary[SimpleBase]

case class SophisticatedBaseSummary(s