quicktype icon indicating copy to clipboard operation
quicktype copied to clipboard

Allow for custom enum `CodingKey` raw-values in Swift

Open markst opened this issue 2 years ago • 3 comments

I am working on a project where I need to generate Swift Codable structures from a JSON Schema, and I'm interested in customizing the generated Swift Enum CodingKey raw values. Specifically, I want to use custom values defined within my JSON Schema as the raw values for CodingKeys, rather than the property names themselves.

For example, let's consider the following JSON Schema:

{
  "definitions": {
    "Application": {
      "type": "object",
      "properties": {
        "device": {
          "type": "object",
          "properties": {
            "brand": {
              "type": "string",
              "description": "The brand of the device",
              "appEquivalent": "deviceBrand",
              "enum": ["News", "Local", "Radio National", "Other"]
            }
          },
          "required": ["brand"]
        }
      },
      "required": ["device"]
    }
  }
}

Here, the "brand" property has a custom attribute "appEquivalent": "deviceBrand", which I want to use as the raw value for the corresponding CodingKeys case. This would change the generated code from:

enum CodingKeys: String, CodingKey {
  case brand = "brand"
}

To:

enum CodingKeys: String, CodingKey {
  case brand = "deviceBrand"
}

I've been looking into how this might be achieved, and it seems that I would need to override the getEnumPropertyGroups method in my SwiftRenderer subclass. Here's a hypothetical example:

class CustomSwiftRenderer extends SwiftRenderer {
  protected getEnumPropertyGroups(c: ClassType): PropertyGroup[] {
    let groups: PropertyGroup[] = super.getEnumPropertyGroups(c);
    
    for (let group of groups) {
      for (let property of group.properties) {
        const equivalentValue = property.jsonSchema.get('appEquivalent');
        if (equivalentValue !== undefined) {
          property.jsonName = equivalentValue;
        }
      }
    }

    return groups;
  }
}

I'd like to know if this is the right approach, and if there's any advice or guidance that could help me in implementing this feature?

markst avatar Jul 30 '23 02:07 markst

To expand upon which might inform. I'm also looking to be able to define multiple CodingKey based on my JSONSchema. Such as:

struct Application: Codable {
    let environment: Environment
    let platform: Platform
    let device: Device
    let product: String
    let brand: Brand

    enum CodingKeys: String, CodingKey {
        case environment = "a_environment"
        case platform = "a_platform"
        case device = "a_device"
        case product = "a_product"
        case brand = "a_brand"
    }
    
    enum GATrackingKeys: String, CodingKey {
        case environment = "cd73"
        case platform = "cd74"
        case device = "cd75"
        case product = "cd76"
        case brand = "cd77"
    }
}

Which seemingly might require multiple passes at getEnumPropertyGroups

markst avatar Jul 30 '23 02:07 markst

I guess requirements might require somewhat similar changes to @Ecarrion's work on: #1215 #1218 #1223

markst avatar Jul 30 '23 02:07 markst

#1158

markst avatar Jul 30 '23 04:07 markst