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

Schema re-use: "propertyNames" instead of "additionalProperties": false #214

Closed
handrews opened this issue Dec 28, 2016 · 6 comments
Closed
Labels
clarification Items that need to be clarified in the specification question

Comments

@handrews
Copy link
Contributor

handrews commented Dec 28, 2016

Now that we have "propertyNames", it is easier to cause validation to fail on unexpected properties without using "additionalProperties" false. The general idea is that names in "properties" become an "enum" in "propertyNames", while each pattern in "patternProperties" becomes a "pattern" in "propertyNames".

While the names and patterns still must be listed twice, it is possible to do this for each schema that needs to be re-used and then combine them however you want. This makes the process relatively easy to manage with well-structured "definitions" (and perhaps we can come up with a way to make it simpler?)

{
    "definitions": {
        "fooSchema": {
            "properties": {
                "foo1": {"type": "number"},
                "foo2": {"type": "boolean"}
            },
            "patternProperties": {
                "foo[A-Z][a-z0-9]*": {"type": "string"}
            }
        },
        "fooProperties": {
            "propertyNames": {
                "$comment": "Need to anyOf these or else the enum and pattern conflict",
                "anyOf": [
                    {"enum": ["foo1", "foo2"]},
                    {"pattern": "foo[A-Z][a-z0-9]*"}
                ]
            }
        },
        "barSchema": {
            "bar1": {"type": "null"},
            "bar2": {"type": "integer"}
        },
        "barProperties": {
            "propertyNames": {"enum": ["bar1", "bar2"]}
        }
    },
    "$comment": "Even with allOf schemas, need anyOf propertyNames or else they conflict",
    "allOf": [
        {"$ref": "#/definitions/fooSchema"},
        {"$ref": "#/definitions/barSchema"}
    ],  
    "anyOf": [
        {"$ref": "#/definitions/fooProperties"},
        {"$ref": "#/definitions/barProperties"}
    ]
}

This is much better than:

{
    "definitions": {
        "fooSchema": {
            "properties": {
                "foo1": {"type": "number"},
                "foo2": {"type": "boolean"}
            },
            "patternProperties": {
                "foo[A-Z][a-z0-9]*": {"type": "string"}
            }
        },
        "barSchema": {
            "bar1": {"type": "null"},
            "bar2": {"type": "integer"}
        }
    },
    "allOf": [
        {"$ref": "#/definitions/fooSchema"},
        {"$ref": "#/definitions/barSchema"},
        {
            "properties": {
                "foo1": true,
                "foo2": true,
                "bar1": true,
                "bar2": true
            },
            "patternProperties": {
                "foo[A-Z][a-z0-9]*": true
            },
            "additionalProperties": false
        }
    ]
}

In this version, you have to construct the correct "additionalProperties": false schema for every combination individually. With the "anyOf" + "propertyNames" approach, you can package up the property name rules and re-use them as easily as you do the corresponding schemas.

While this is not the simplest construct possible, it is much simpler than "$combine"/"$combinable", (#119) and unlike "$merge"/"$patch" (#15) it cannot be abused to produce JSON that is not even a schema, or to splice things in ways that authors of the source of the splice never intended.

I feel like this is a more promising avenue than the other proposals so far. Would it be reasonable to recommend this and put some guidance on the web site and see how that goes in draft 6? Then maybe we'll find that we don't really need the more complex solutions at all.

@epoberezkin
Copy link
Member

epoberezkin commented Dec 29, 2016

@handrews I can't understand that at all. I suggest you stop coming up with new ideas for today, seriously...

additionalProperties validates property values. Objects can be just dictionaries, when all properties should be valid according to the same schema. Then you just use additionalProperties and that's it. propertyNames validates, well property names. There are cases when you need both. The fact that you can additionalProperties: false is just a consequence of boolean schemas now. How one can replace another?

@epoberezkin
Copy link
Member

Or are you talking about general usage pattern? Than why it is in issue?

@handrews
Copy link
Contributor Author

It is a usage pattern for "solving" the perennial "I want to error out if I see an unexpected property, but I want to be able to combine schemas that error on unexpected properties into a schema that only errors when it sees a property that is not in any of them" problem.

It is an issue because we don't really have anywhere else to discuss these things as there's hardly any activity on the mailing list. When I post there it often sinks without a trace, so I stopped.

Then you just use additionalProperties and that's it. propertyNames validates, well property names. There are cases when you need both. The fact that you can additionalProperties: false is just a consequence of boolean schemas now. How one can replace another?

Nothing's replacing anything. I'm well aware of how "additionalProperties" (boolean or otherwise) works. But people use (abuse) "additionalProperties": false as an error-checking tool. You know this, you've been involved in discussions in many of the other proposals for solving this.

I suggest you stop coming up with new ideas for today, seriously...

Perhaps you should read more carefully, seriously...

@handrews
Copy link
Contributor Author

There's not really anything to do with the spec here, so I've moved this to: json-schema-org/json-schema-org.github.io#77

@handrews
Copy link
Contributor Author

@Text-only I'm not sure why you're frowny-facing a closed issue from four years ago? This problem was solved in a completely different way two drafts ago- this particular issue/proposal is long obsolete. Even the "design pattern" documentation issue was closed as it is no longer at all needed.

@gregsdennis gregsdennis added clarification Items that need to be clarified in the specification and removed feedback labels Jul 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clarification Items that need to be clarified in the specification question
Projects
None yet
Development

No branches or pull requests

4 participants
@handrews @gregsdennis @epoberezkin and others