guardrail-dev / guardrail-dev/guardrail

schema and scala type names conflicts

Open
#1,147 2 comments 0 reactions 0 assignees View on GitHub
good first issue scala
Dominant language
Scala
Stars
541
Forks
138
PR merge metrics
No merged PRs in 30d

Description

Hi,

i have following schema

```yaml
Product:
type: object
properties:
id:
type: string
type:
$ref: '#/components/schemas/Type'
required:
- shape
- id
Type:
type: string
enum:
- Service
- Digital
```

which generate following code

```scala
package com.product.api

import cats.syntax.either._
import io.circe._
import io.circe.syntax._
import cats.implicits._
import _root_.com.upstartcommerce.catalog2.api.openapi.Implicits._
case class Product(id: String, `type`: Option[Type] = None)
object Product {
implicit val encodeProduct: Encoder.AsObject[Product] = {
val readOnlyKeys = Set[String]()
Encoder.AsObject.instance[Product](a => JsonObject.fromIterable(Vector(("id", a.id.asJson), ("type", a.`type`.asJson)))).mapJsonObject(_.filterKeys(key => !(readOnlyKeys contains key)))
}
implicit val decodeProduct: Decoder[Product] = new Decoder[Product] { final def apply(c: HCursor): Decoder.Result[Product] = for (v0 <- c.downField("id").as[String]; v1 <- c.downField("type").as[Option[Type]]) yield Product(v0, v1) }
}

sealed abstract class Type(val value: String) extends Product with Serializable { override def toString: String = value.toString }
object Type {
object members {
case object Service extends Type("Service")
case object Digital extends Type("Digital")
}
val Service: Type = members.Service
val Digital: Type = members.Digital
val values = Vector(Service, Digital)
implicit val encodeType: Encoder[Type] = Encoder[String].contramap(_.value)
implicit val decodeType: Decoder[Type] = Decoder[String].emap(value => from(value).toRight(s"$value not a member of Type"))
implicit val showType: Show[Type] = Show[String].contramap[Type](_.value)
def from(value: String): Option[Type] = values.find(_.value == value)
implicit val order: cats.Order[Type] = cats.Order.by[Type, Int](values.indexOf)
}
```

however there is a problem there, as com.product.api.Product, overrides scala.Product of

```scala
sealed abstract class Type(val value: String) extends Product
```

i think that generated code should have full class names, to avoid those types of conflicts.

```scala
sealed abstract class Type(val value: String) extends _root_.scala.Product
```
and probably not just for Product, also for io.circe.Encoder ..., to avoid conflicts with names in defined schema

what do you think about that?

thank you for your response

Peter

Contributor guide

Open the contributing guide

Research direction

Start with the OpenAPI schema and generated Scala output shown in the issue, focusing on the generated Type/Product inheritance and referenced Encoder types. Reproduce the naming collision with the provided Product and Type schemas, then verify that generated references remain unambiguous when schema names conflict with Scala or imported types.

Written by the indexing model from the issue text.

Assessment

Tech stack
openapi, scala
Domain
backend-api-design, devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.