bhch / django-jsonform

A better, user-friendly JSON editing form field for Django admin. Also supports Postgres ArrayField.
https://django-jsonform.rtfd.io
BSD 3-Clause "New" or "Revised" License
307 stars 31 forks source link

Issue with errors for fields inside an anyOf schema not displaying correctly #160

Open trumpet2012 opened 3 months ago

trumpet2012 commented 3 months ago

Hi!

Want to start by saying thanks for writing and maintaining this package.

I noticed an issue with handling validation errors for values inside a anyOf (and likely oneOf) not being surfaced as expected. If you have any anyOf that further down contains a number field with a minimum set, instead of getting back an error message on the number field when you enter a value below the minimum, you get a generic error saying "Some required fields are missing" above the django field.

An example schema to reproduce this below:

{
    "type": "object",
    "properties": {
        "add": {
            "type": "array",
            "items": {
                "anyOf": [
                    {
                        "type": "object",
                        "keys": {
                            "length": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "title": "Length (in)"
                            },
                            "width": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "title": "Width (in)"
                            },
                            "height": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "title": "Height (in)"
                            }
                        },
                        "required": ["length", "width", "height"]
                    },
                    {
                        "type": "object",
                        "keys": {
                            "length": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "title": "Length (in)"
                            },
                            "diameter": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "title": "Diameter (in)"
                            }
                        },
                        "required": ["length", "diameter"]
                    }
                ]
            }
        }
    }
}

I looked into the JSONSchemaValidator and believe I have identified why this is happening. Looking at the implementation of validate_anyOf (this also applies to oneOf equivalent) it is relying on the possible subschemas validate functions to not raise an exception if the schema matches the data. However if you have min/max rules on some fields in the subschema it will raise the same exception making the anyOf check think that the schema isn't a match. Then once it loops through all of the possible subschemas and doesn't find a match it raises the "Some required fields are missing" exception.

In the meantime my workaround is to implement a custom validator to handle these minimum value checks.

bhch commented 3 months ago

The validator can't know which subschema the user has selected (because that info is UI related and is never transferred to the backend). So we have to loop over all the subschemas to try and find a match for the given data.

We probably need a better way to find a match.