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 inference metric too conservative? #757

Open
rjstelling opened this issue Apr 5, 2018 · 3 comments
Open

Enum inference metric too conservative? #757

rjstelling opened this issue Apr 5, 2018 · 3 comments
Labels
good first issue Not necessarily easy, but doesn't require deep quicktype knowledge

Comments

@rjstelling
Copy link

I have the below JSON and using this command:

$ quicktype --alphabetize-properties --density normal --no-initializers --src example.json --lang swift --top-level "Certificate" -o out.swift

I don't not get enums for Switch.type (see output below).

Input

{
    "expires": 1519873431,
    "modules": [
        {
            "name": "FPKit",
            "switches": [
                {
                    "key": "valueA",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "valueB",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "valueC",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "valueD",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "valueE",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "valueF",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "valueG",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "valueH",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "valueI",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "valueJ",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "value2",
                    "type": "int",
                    "type_info": null,
                    "value": "2"
                },
                {
                    "key": "value3",
                    "type": "double",
                    "type_info": null,
                    "value": "3.5"
                },
                {
                    "key": "value3a",
                    "type": "double",
                    "type_info": null,
                    "value": "3.5"
                },
                {
                    "key": "value4",
                    "type": "bool",
                    "type_info": null,
                    "value": "true"
                },
                {
                    "key": "value5",
                    "type": "data",
                    "type_info": null,
                    "value": "vafEXVIgdfg;svjKLIger/wFFFdfvkjadlluulfhj567gnlCWuukgj6dv5vCECWWaM,PiOEFGjdsv=="
                },
                {
                    "key": "value5a",
                    "type": "custom",
                    "type_info": "UIColor",
                    "value": "vafEXVIgdfg;svjKLIger/wFFFdfvkjadlluulfhj567gnlCWuukgj6dv5vCECWWaM,PiOEFGjdsv=="
                },
                {
                    "key": "value5b",
                    "type": "custom",
                    "type_info": "UIColor",
                    "value": "vafEXVIgdfg;svjKLIger/wFFFdfvkjadlluulfhj567gnlCWuukgj6dv5vCECWWaM,PiOEFGjdsv=="
                }
            ]
        },
        {
            "name": "main",
            "switches": [
                {
                    "key": "value",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "value",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "value2",
                    "type": "int",
                    "type_info": null,
                    "value": "2"
                },
                {
                    "key": "value3",
                    "type": "double",
                    "type_info": null,
                    "value": "3.5"
                },
                {
                    "key": "valuea",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "valueb",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                },
                {
                    "key": "value2",
                    "type": "int",
                    "type_info": null,
                    "value": "2"
                },
                {
                    "key": "value3",
                    "type": "double",
                    "type_info": null,
                    "value": "3.5"
                },
                {
                    "key": "value4",
                    "type": "bool",
                    "type_info": null,
                    "value": "true"
                },
                {
                    "key": "value4",
                    "type": "bool",
                    "type_info": null,
                    "value": "true"
                },
                {
                    "key": "value5b",
                    "type": "data",
                    "type_info": null,
                    "value": "vafEXVIgdfg;svjKLIger/wFFFdfvkjadlluulfhj567gnlCWuukgj6dv5vCECWWaM,PiOEFGjdsv=="
                },
                {
                    "key": "value5a",
                    "type": "custom",
                    "type_info": "UIColor",
                    "value": "vafEXVIgdfg;svjKLIger/wFFFdfvkjadlluulfhj567gnlCWuukgj6dv5vCECWWaM,PiOEFGjdsv=="
                },
                {
                    "key": "valuec",
                    "type": "string",
                    "type_info": null,
                    "value": "hello world"
                }
            ]
        }
    ],
    "signature": "vafEXVIgdfg;fEXVIgdfg;svjKLbsfgbfs%$^&*YHkbjvgkccIger/;svjKLIger/wFFFdfvkFdfvkjCWWaM,PiGjdsv==",
    "version": 1
}

Output

// To parse the JSON, add this file to your project and do:
//
//   let certificate = try? JSONDecoder().decode(Certificate.self, from: jsonData)

import Foundation

struct Certificate: Codable {
    let expires: Int
    let modules: [Module]
    let signature: String
    let version: Int

    enum CodingKeys: String, CodingKey {
        case expires = "expires"
        case modules = "modules"
        case signature = "signature"
        case version = "version"
    }
}

struct Module: Codable {
    let name: String
    let switches: [Switch]

    enum CodingKeys: String, CodingKey {
        case name = "name"
        case switches = "switches"
    }
}

struct Switch: Codable {
    let key: String
    let type: String
    let typeInfo: String?
    let value: String

    enum CodingKeys: String, CodingKey {
        case key = "key"
        case type = "type"
        case typeInfo = "type_info"
        case value = "value"
    }
}
@dvdsgl
Copy link
Member

dvdsgl commented Apr 5, 2018

I know this isn't what you're asking for, but FYI, we now support TypeScript input for more control over generated types. Given the file certificate.ts:

class Certificate {
    /** @TJS-type integer */
    expires:   number;
    modules:   Module[];
    signature: string;
    /** @TJS-type integer */
    version:   number;
}

class Module {
    name:     string;
    switches: Switch[];
}

class Switch {
    key:        string;
    type:       "string" | "custom" | "data" | "bool" | "double" | "int";
    type_info?: string;
    value:      string;
}

You can get the Swift you want with:

$ quicktype \
    --alphabetize-properties --density normal --no-initializers \
    --src certificate.ts --lang swift --top-level "Certificate" -o out.swift

Or more succinctly:

$ quicktype certificate.ts -o out.swift \
    --alphabetize-properties --density normal --no-initializers

@schani
Copy link
Member

schani commented Apr 5, 2018

Our metric needs to see more values before it will infer type as an enum. Adding a few by hand works. Maybe it's too conservative?

@schani schani changed the title Why does this JSON not generate Enums? Enum inference metric too conservative? Apr 5, 2018
@rjstelling
Copy link
Author

Yes, tripling the "switches" sorted it.

Yes, I would say it was a bit conservative, maybe a threshold switch on the cli?

@schani schani added the good first issue Not necessarily easy, but doesn't require deep quicktype knowledge label Aug 15, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Not necessarily easy, but doesn't require deep quicktype knowledge
Projects
None yet
Development

No branches or pull requests

3 participants