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

Enum classes are duplicated and corrupt #351

Open
huehnerlady opened this issue May 19, 2021 · 3 comments
Open

Enum classes are duplicated and corrupt #351

huehnerlady opened this issue May 19, 2021 · 3 comments
Assignees
Labels

Comments

@huehnerlady
Copy link

huehnerlady commented May 19, 2021

Hi,

I am trying to use your project as a lib to generate our API classes from a json schema.
I ran into the following problem:
When there is an enum in the class, I could see 2 problems:

  1. The class is generated for every declaration
  2. The values of the enum are not with a String, so the code does not compile. -> see classes which are references are duplicated #352
    Example:
    I have a json schema:
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "Foo",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "value1": {
      "type": "string"
    },
    "value2": {
      "type": "string",
      "$ref": "#/definitions/FooEnum"
    },
    "value3": {
      "type": "string",
      "$ref": "#/definitions/FooEnum"
    }
  },
  "definitions": {
    "FooEnum": {
      "type": "string",
      "enum": [
        "VALUE_1",
        "VALUE_2",
        "VALUE_3"
      ]
    }
  }
}

I would expect the following code to come out of this:

data class Foo(
    val value1: String? = null,
    val value2: FooEnum? = null,
    val value3: FooEnum? = null
) {
  enum class FooEnum(val value: String) {
    VALUE_1("VALUE_1"),

    VALUE_2("VALUE_2"),

    VALUE_3("VALUE_3");
  }
}

but I get:

data class Foo1(
    val value1: String? = null,
    val value2: FooEnum? = null,
    val value3: FooEnum? = null
) {
  enum class FooEnum(val value: String) {
    VALUE_1(VALUE_1),

    VALUE_2(VALUE_2),

    VALUE_3(VALUE_3);
  }

  enum class FooEnum(val value: String) {
    VALUE_1(VALUE_1),

    VALUE_2(VALUE_2),

    VALUE_3(VALUE_3);
  }
}

Unfortunately this does not compile with the following errors:

  • Duplicate JVM class name 'de/europace/privatkredit/kex/vorgaenge/api/Foo1$FooEnum' generated from: FooEnum, FooEnum
  • Type mismatch. Required:String, Found:Foo1.FooEnum

I am currently using the lib wu.seal.jsontokotlin:library:3.6.1

My generation code:

val file = File("Foo.json")
  val jsonString = file.readText()
  val actualOutput = JsonToKotlinBuilder()
      .setPackageName("some.package")
      .enableVarProperties(false) // optional, default : false
      .setPropertyTypeStrategy(PropertyTypeStrategy.Nullable) // optional, default :  PropertyTypeStrategy.NotNullable
      .setDefaultValueStrategy(DefaultValueStrategy.AllowNull) // optional, default : DefaultValueStrategy.AvoidNull
      .setAnnotationLib(TargetJsonConverter.None) // optional, default: TargetJsonConverter.None
      .enableOrderByAlphabetic(true) // optional : default : false
      .enableInnerClassModel(true) // optional, default : false
      .enableCreateAnnotationOnlyWhenNeeded(true) // optional, default : false
      .setIndent(2) // optional, default : 4
      .enableKeepAnnotationOnClass(false) // optional, default : false
      .enableKeepAnnotationOnClassAndroidX(false) // optional, default : false
      .enableAnnotationAndPropertyInSameLine(false) // optional, default : false
      .enableParcelableSupport(false) // optional, default : false
      .build(jsonString, "Foo") // finally, get KotlinClassCode string
  val kotlinClass = File("Api.kt")
  kotlinClass.createNewFile()
  kotlinClass.writeText(actualOutput)
@wuseal
Copy link
Owner

wuseal commented May 20, 2021

@TedZen PLS check this

@KundlJ
Copy link

KundlJ commented Jun 30, 2021

I've experienced the same issue. I believe it's due to this line:

I think it should read:
val constantValue: Any = when (i) {
instead of
val constantValue: Any = when (generic) {

But I'm not certain. I was planning on cloning the repo and seeing whether that'd fix it later, but if someone more familiar can look at that and be like "ah, yes" that'd be awesome.

@KundlJ
Copy link

KundlJ commented Jul 1, 2021

After checking out the repo and poking around I realize my previous thought was incorrect, however in looking at the test code

.
.
.
"definitions": {
    "LogEventType": {
      "type": "integer",
      "description": "",
      "x-enumNames": [
        "Undefined",
        "Auth"
      ],
      "enum": [
        0,
        1
      ]
    }
  }
}
    """.trimIndent()

    val expectedEnum = """
        enum class LogEventType(val value: Int) {
            Undefined(0),

            Auth(1);
        }
    """.trimIndent()

I realized that JsonToKotlinClass expects x-enumNames for enum names and uses enum for enum values.

A solution that worked for me was to add escaped quotations into the enum fields. I'm not sure whether this conforms to json schema spec.

Example using the schema from the test code:

"definitions": {
    "LogEventType": {
      "type": "string",
      "description": "",
      "x-enumNames": [
        "Undefined",
        "Auth"
      ],
      "enum": [
        "\"Undefined\"",
        "\"Auth\""
      ]
    }
  }
}

Produces

enum class LogEventType(val value: String) {
            Undefined("Undefined"),

            Auth("Auth");
        }

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

4 participants