ajv-validator / ajv-errors

Custom error messages in JSON Schemas for Ajv validator
https://ajv.js.org
MIT License
284 stars 19 forks source link

Keyword messages for 'required' and 'additionalProperties' not replaced when ajv's errorDataPath is set to 'property' #12

Open nathanchrs opened 7 years ago

nathanchrs commented 7 years ago

According to the docs, 'for keywords "required" and "dependencies" it is possible to specify different messages for different properties'. However, when using ajv-errors with errorDataPath set to property, keyword messages are ignored.

The situation is exactly the same as in the test should replace required and dependencies errors with messages, with the exception of the errorDataPath being set for ajv in this case.

Is this an intended consequence of setting errorDataPath to property?

epoberezkin commented 7 years ago

Is this an intended consequence of setting errorDataPath to property?

@nathanchrs yes, I was actually going to deprecate this option in Ajv, it was added for backward compatibility only long time ago. It won't be supported here, probably worth adding some warning if it's set.

nathanchrs commented 7 years ago

Actually I've just found a workaround for my use case, by using the following schema:

{
  'type': 'object',
  'properties': {
    'someRequiredProperty': {
      'type': 'string',
      'format': 'email',
      'errorMessage': 'Must be a valid email (or any kind of validation)'
    }
  },
  'required': ['someRequiredProperty'],
  'errorMessage': {
    'properties': {
      'someRequiredProperty': 'This is required'
    }
  }
}

My use case still requires errorDataPath to be set to property, though. I am working on client-side form validation and I need the missing property names, so that I can display errors next to their corresponding inputs. From what I understand in #255, using errorDataPath: 'property' the only way to get the property names. Maybe there's a better way?

Thanks!

epoberezkin commented 7 years ago

I am working on client-side form validation and I need the missing property names, so that I can display errors next to their corresponding inputs

You can process errors and give "required" keyword errors a special treatment to associate them with a form field.

ashnur commented 6 years ago

"You can process errors" - this is left to be demonstrated, until then it's only theory.

epoberezkin commented 6 years ago

"You can process errors" - this is left to be demonstrated, until then it's only theory.

Not sure what you mean. Errors are just array of objects with the documented structure, so they can be processed as any other data structure - what's there to be proven? You just need to write code to process this data structure.

ashnur commented 6 years ago

You just need to write code to process this data structure.

Of course I have to write code that processes data-structures, that's basically the job description of a software programmer, however in most cases there is an API and a documentation and most importantly, the data-structure is well thought out and actually helps solving the problem instead of making the programmer's life harder. At least in the case of good data-structures that are well designed.

Not sure what you mean. Errors are just array of objects with the documented structure, so they can be processed as any other data structure - what's there to be proven?

See, the problem is that after I wrote a bunch of schemas that describe the structure of the data I work with and I want to validate, and I run my data through your validator with my schema, and your validator (which is great btw.) gives back the errors, for some unknown and completely mind boggling reason, instead of getting the response back in the structure I have specified as relevant to my software, I get a damned array. AN ARRAY. If my schema would be "just an array of objects", I wouldn't need to validate my schema much, would I? The whole point of using schema is to keep the structure around. Now, with your list of errors, I would love to see the processing code that puts together the list into the original schema structure that was validated, because honestly, I am not sure if it's possible or if it is, it's worth the effort, as I would probably lose any kind of performance benefits I gained in the beginning.

epoberezkin commented 6 years ago

A related discussion is here: https://github.com/json-schema-org/json-schema-spec/issues/396#issuecomment-407890886

The problem with achieving what you want is that, by design, the JSON schema is 1) not declaring the structure of the data and 2) can have very different structure from the data.

So returning the array of errors makes the most sense, in general case.

The analogy here is the stack trace of the exception - even though it represents the tree of functions, it’s is logged as a simple list.

In some specific cases, like the one you most likely have, it is possible to return errors in a format that is close to the structure of the data, and such structure can be created from the array of errors. But it is not possible in the general case, because it is not always possible to attribute an error to a specific location in the data.

ashnur commented 6 years ago

I've read those comments weeks ago. I realize that JSONSchema doesn't describe a fixed tree structure that could be simply dereferenced into a unit. But this doesn't mean, that there is no relevant structure at the time of validation that could be exported and shared. There is always a path of data pointers and schema pointers that we've followed and that we have to use for validation, and a lot of the time it would be useful to optionally have either of them instead of having fed a premade choice based on assumptions by the library author and not the library user.

Exactly like stack trace, however you are not giving me a stack, you are giving me an error log with meta-data that also have meta-data :). If you were giving me the stack, I would be probably content with that however there is more than this.

I realize that errors as data from the perspective of the writer of the validation library is a good decision, solves a bunch of problems, it's easy and fast. However if it is hard for you to give back structural information while you have ALL THE INFO, imagine how hard it is to parse the errors for someone who has less than that. I am jumping through hoops to somehow find how to pair my DOM Nodes that should show a text with your errors and basically it seems that the best way is to create a huge map of some kind, a 3rd data structure.

That's not a scalable approach for a general solution

What you miss I think is that I do not want you to match my errors to some pre-defined schema, that's not going to work for everyone, I know, because how flexible JSONSchema is, and actually that's one of the main reasons I am using it.

What I miss is that why can't we have more than just one data structure for the errors? Why does it have to be a list of complicated error objects, why not something that's easier to parse and that contains more information? This isn't about just required and such keywords, but also references and errors from if/then/else and custom keywords too. If I want a general solution for recognizing the source of the errors, I can not build on your software, because I feel that I would have to re-do most of the work you already did just for this tiny little detail of how the errors are reported.

I believe that this is all about lost contextual information. You perhaps feel that you have not hidden anything, but in fact the current path and pointers data that seems sometimes duplicated (btw, duplication is way better than bad abstractions, I hate when people avoid a couple of bytes of additional data because of some false sense of aesthetics https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction , because you also seem to believe that having the same bits in more than one place is somehow wrong https://github.com/epoberezkin/ajv/issues/255#issuecomment-237045449)

For example, I would be happy with a solution where instead of having to read a list of arcane objects, I could give one or more (but not too many) callbacks to be called on error detection, I would get all the contextual information and I could build my own error data structure that would fit my needs not yours. I could do all kinds of processing around the error without anyone else being affected.