Skip to content

[json_syntax_generator] Tagged unions with tag outside union #2440

@dcharkes

Description

@dcharkes

The syntax generator supports:

[
  {
    "type": "foo"
    "foo_field": "bar"
  },
  {
    "type": "bar"
    "bar_field": "bar"
  },
]

And it creates separate subclasses of the shared super class based on "type" being the tag for the tagged union. Moreover, it makes the factory constructor on the shared super class look at the the tag and instantiate the right subclass.

However, sometimes JSON schemas don't have a clear tag that describes the whole thing. Rather one field having a value means another field is constrained in some way. We already support this "if-field-x-has-value-y-then-field-z-is-required", but we don't yet support "if-field-x-has-value-y-then-field-z-has-type-a".

One example from

"Package": {
"type": "object",
"required": [
"dependency",
"description",
"source",
"version"
],
"properties": {
"dependency": {
"$ref": "#/definitions/DependencyType"
},
"description": {
"$ref": "#/definitions/PackageDescription"
},
"source": {
"$ref": "#/definitions/PackageSource"
},
"version": {
"$ref": "#/definitions/PackageVersion"
}
},
"additionalProperties": false
},

which should constraint description based on what source is used:

        "Package": {
            "type": "object",
            "required": [
                "dependency",
                "description",
                "source",
                "version"
            ],
            "properties": {
                "dependency": {
                    "$ref": "#/definitions/DependencyType"
                },
                "description": {
                    "$ref": "#/definitions/PackageDescription"
                },
                "source": {
                    "$ref": "#/definitions/PackageSource"
                },
                "version": {
                    "$ref": "#/definitions/PackageVersion"
                }
            },
            "allOf": [
                {
                    "if": {
                        "properties": {
                            "source": {
                                "const": "git"
                            }
                        }
                    },
                    "then": {
                        "properties": {
                            "description": {
                                "$ref": "#/definitions/GitPackageDescription"
                            }
                        }
                    }
                },
                {
                    "if": {
                        "properties": {
                            "source": {
                                "const": "hosted"
                            }
                        }
                    },
                    "then": {
                        "properties": {
                            "description": {
                                "$ref": "#/definitions/HostedPackageDescription"
                            }
                        }
                    }
                },
                {
                    "if": {
                        "properties": {
                            "source": {
                                "const": "path"
                            }
                        }
                    },
                    "then": {
                        "properties": {
                            "description": {
                                "$ref": "#/definitions/PathPackageDescription"
                            }
                        }
                    }
                }
            ],
            "additionalProperties": false
        },

Not intending to support this now, but filing an issue to point to in tests.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions