glideapps / quicktype

Generate types and converters from JSON, Schema, and GraphQL

Home Page:https://app.quicktype.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

JSON Schema generation differs between Python and other languages [Rust, Dart, Kotlin]

elyoni opened this issue · comments

I would like to report an issue concerning the generation of JSON Schema, which appears to differ between Python and other programming languages such as Rust, Dart, and Kotlin.

The problem arises when generating a Python class using the provided JSON Schema. In Python, the resulting variable types are unusable. For instance, the variable "parameters" is defined as a dictionary, where every value is expected to be None. However, in Rust (for example), the corresponding type is "JSON," not None.

Specifically, the issue lies in the type assigned to the dictionary values. In Python, they are consistently set to None, whereas in Rust, they are assigned the type "JSON." This inconsistency causes problems when using the "from_dict" function, as it checks that every value in the dictionary is None.

I believe addressing this discrepancy in JSON Schema generation between Python and other supported languages would greatly enhance the usability and compatibility of Quicktype. I hope this issue can be resolved to ensure a consistent experience for developers across all languages.

JSON Schema

{
    "$schema": "http://json-schema.org/draft-04/schema#",
        "properties": {
            "CommandArgs": {
                "required": [
                    "commandUri"
                ],
                "type": "object",
                "properties": {
                    "commandUri": {
                        "type": "string"
                    },
                    "parameters": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "null"
                        }
                    }
                }
            },
            "CommandResp": {
                "type": "object",
                "properties": {
                    "resultFields": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "null"
                        }
                    }
                }
            }
        }
}

Python Output

from typing import Dict, Optional


class CommandArgs:
    commandUri: str
    parameters: Optional[Dict[str, None]]  # <----- My Issue

    def __init__(self, commandUri: str, parameters: Optional[Dict[str, None]]) -> None:    # <----- My Issue
        self.commandUri = commandUri
        self.parameters = parameters


class CommandResp:
    resultFields: Optional[Dict[str, None]]  # <----- My Issue

    def __init__(self, resultFields: Optional[Dict[str, None]]) -> None:     # <----- My Issue
        self.resultFields = resultFields

class DRClass:
    CommandArgs: Optional[CommandArgs]
    CommandResp: Optional[CommandResp]

    def __init__(self, CommandArgs: Optional[CommandArgs], CommandResp: Optional[CommandResp]) -> None:
        self.CommandArgs = CommandArgs
        self.CommandResp = CommandResp

    @staticmethod
    def from_dict(obj: Any) -> 'DRClass':
        assert isinstance(obj, dict)
        CommandArgs = from_union([CommandArgs.from_dict, from_none], obj.get("CommandArgs"))  # <----- My Issue
        CommandResp = from_union([CommandResp.from_dict, from_none], obj.get("CommandResp"))  # <----- My Issue
        return DRClass(CommandArgs, CommandResp)

    def to_dict(self) -> dict:
        result: dict = {}
        if self.CommandArgs is not None:
            result["CommandArgs"] = from_union([lambda x: to_class(CommandArgs, x), from_none], self.CommandArgs)  # <----- My Issue
        if self.CommandResp is not None:
            result["CommandResp"] = from_union([lambda x: to_class(CommandResp, x), from_none], self.CommandResp)  # <----- My Issue
        return result