ajv: Include property name in error object

Hi, I’m passing in a schema and getting a collection of errors back. However, I need to know the property that is causing the error. In the error object, there is “dataPath” however, most of the time that value is “”. When it does show it, it is in the path notation as explained in the docs, and I would still have to parse it to get the name, but more importantly, most of the time it’s blank. If it’s a required field error I can dig into the “params” and get missing field, but if it’s a format error then I’d have to have different logic. I suspect I’m doing something wrong, so I’m include some data.

this is what the out put of the errors array looks like, and it’s in verbose, sorry trying to be thorough.

[
    {
        "keyword": "format",
        "dataPath": ".startTime",
        "schemaPath": "#/properties/startTime/format",
        "params": {
            "format": "time"
        },
        "message": "should match format \"time\"",
        "schema": "time",
        "parentSchema": {
            "type": "string",
            "format": "time"
        },
        "data": ""
    },
    {
        "keyword": "required",
        "dataPath": "",
        "schemaPath": "#/required",
        "params": {
            "missingProperty": "endTime"
        },
        "message": "should have required property 'endTime'",
        "schema": {
            "id": {
                "type": "string",
                "format": "uuid"
            },
            "startTime": {
                "type": "string",
                "format": "time"
            },
            "endTime": {
                "type": "string",
                "format": "time"
            },
            "display": {
                "type": "string"
            },
            "color": {
                "description": "color to display tasks",
                "type": "string"
            }
        },
        "parentSchema": {
            "title": "Example Schema",
            "type": "object",
            "properties": {
                "id": {
                    "type": "string",
                    "format": "uuid"
                },
                "startTime": {
                    "type": "string",
                    "format": "time"
                },
                "endTime": {
                    "type": "string",
                    "format": "time"
                },
                "display": {
                    "type": "string"
                },
                "color": {
                    "description": "color to display tasks",
                    "type": "string"
                }
            },
            "required": [
                "startTime",
                "endTime",
                "display",
                "color"
            ]
        },
        "data": {
            "startTime": ""
        }
    },
    {
        "keyword": "required",
        "dataPath": "",
        "schemaPath": "#/required",
        "params": {
            "missingProperty": "display"
        },
        "message": "should have required property 'display'",
        "schema": {
            "id": {
                "type": "string",
                "format": "uuid"
            },
            "startTime": {
                "type": "string",
                "format": "time"
            },
            "endTime": {
                "type": "string",
                "format": "time"
            },
            "display": {
                "type": "string"
            },
            "color": {
                "description": "color to display tasks",
                "type": "string"
            }
        },
        "parentSchema": {
            "title": "Example Schema",
            "type": "object",
            "properties": {
                "id": {
                    "type": "string",
                    "format": "uuid"
                },
                "startTime": {
                    "type": "string",
                    "format": "time"
                },
                "endTime": {
                    "type": "string",
                    "format": "time"
                },
                "display": {
                    "type": "string"
                },
                "color": {
                    "description": "color to display tasks",
                    "type": "string"
                }
            },
            "required": [
                "startTime",
                "endTime",
                "display",
                "color"
            ]
        },
        "data": {
            "startTime": ""
        }
    },
    {
        "keyword": "required",
        "dataPath": "",
        "schemaPath": "#/required",
        "params": {
            "missingProperty": "color"
        },
        "message": "should have required property 'color'",
        "schema": {
            "id": {
                "type": "string",
                "format": "uuid"
            },
            "startTime": {
                "type": "string",
                "format": "time"
            },
            "endTime": {
                "type": "string",
                "format": "time"
            },
            "display": {
                "type": "string"
            },
            "color": {
                "description": "color to display tasks",
                "type": "string"
            }
        },
        "parentSchema": {
            "title": "Example Schema",
            "type": "object",
            "properties": {
                "id": {
                    "type": "string",
                    "format": "uuid"
                },
                "startTime": {
                    "type": "string",
                    "format": "time"
                },
                "endTime": {
                    "type": "string",
                    "format": "time"
                },
                "display": {
                    "type": "string"
                },
                "color": {
                    "description": "color to display tasks",
                    "type": "string"
                }
            },
            "required": [
                "startTime",
                "endTime",
                "display",
                "color"
            ]
        },
        "data": {
            "startTime": ""
        }
    }
]

here is my json.schema

{
  "title": "Example Schema",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "startTime": {
      "type": "string",
      "format": "time"
    },
    "endTime": {
      "type": "string",
      "format": "time"
    },
    "display": {
      "type": "string"
    },
    "color": {
      "description": "color to display tasks",
      "type": "string"
    }
  },
  "required": [
    "startTime",
    "endTime",
    "display",
    "color"
  ]
}

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 15 (8 by maintainers)

Most upvoted comments

So if I understand correctly there are basically only two paths. One is for the required rules, and the other is for the more specific type, format etc rules. You feel that the client can derive what the property is and that is enough, and if it turns out to be pretty straightforward, then that’s cool. I feel that the client should be presented with an easily consumable ( no need for derived or constructed data ) payload, but that is just an opinion. I think perhaps my use case is not a frequent use of the product. I’m trying to use json-spec and ajv to validate my data in as many places as I can, e.g. in an api middleware on the frontend and as client side validation on a property by property level. It is the latter that I guess is not that common a use case and thus what I’m asking for is not that common. In any case, thanks for engaging me and explaining how I can get what I need. R

On Tue, Aug 2, 2016 at 8:34 AM, Evgeny Poberezkin notifications@github.com wrote:

What I was trying to explain is that you mix two different concepts here - the property of the data object in which the error happens (e.g. when you use keywords type, minimum etc.) and the property to which the error is related (when you use required, additionalProperties, dependencies) - in which case the error happens on the object level, not on the property level.

dataPath points to the point in the object where the error happens.

property related to error is always available in error.params.

I don’t think we should add one more property in error object if it doesn’t add any additional information. I think it should be in the application code that processes the errors… I will think about it.

In any case, the structure of error objects for all keywords is documented and it won’t change, not without major version change, so you can rely on it in the code that processes errors.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/epoberezkin/ajv/issues/255#issuecomment-236905449, or mute the thread https://github.com/notifications/unsubscribe-auth/AA12zkIck3UGr-xhB9IhtImO46kU3niiks5qb0degaJpZM4JZKnO .

@epoberezkin thanks for the reply I will try to use errorDataPath: 'property' maybe it really help me.

I don’t understand too how I can create error messages to my html forms with ajv errors. I want to write the algorithm which will be display error messages nearby with input fields, but I can’t understand how it do because within error object from ajv frequently unclear to which the field can be attributed this error. I must figure out it that from dataPath that from missingProperty for require keyword that from devil knows where for custom keyword errors for example validatePassword which I want to display nearby with the password input field.

And the saddest that I can’t find any articles how to use ajv for displaying errors for html forms at frontend.

So if I understand correctly there are basically only two paths. One is for the required rules, and the other is for the more specific type, format etc rules.

Yes, the former pointing to the parent object. You can use the option errorDataPath: 'property' (see Options) that would make dataPath always pointing to the property in question (for keywords required, additionalProperties and dependencies).

What I don’t like about this option is that data property of the error object (with verbose: true option) would still point to the parent object becoming inconsistent with dataPath.

You feel that the client can derive what the property is and that is enough, and if it turns out to be pretty straightforward, then that’s cool.

Kind of. I am fighting the “feature creep” here a little bit… Also I think duplicating the same information in multiple places should be at least considered carefully. As I wrote, I need to think about it…

I feel that the client should be presented with an easily consumable ( no need for derived or constructed data ) payload, but that is just an opinion.

That I agree with. I think it is (at least partially) addressed with message property of errors and also .errorsText method - both include messages that refer to the property in question. Also #100 when implemented would allow to include custom error message generation in the schema, that would most likely address your issue as well. I still hope somebody would implement it, there is even a small bounty for it…

So this is a good explanation of what is happening, but it doesn’t really address the issue that, as a property level validator, this is very difficult to use. I can try and dig in and create a pull request if you’d be open to adding a property value to the error object that would provide a consistent ( between different types of errors ) user experience. Thanks, r