-
-
Notifications
You must be signed in to change notification settings - Fork 873
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
Option to allow type coercion/cast/type conversion. #95
Comments
Thanks. It can be done. You could try using custom keyword (say The option |
+1 for this feature. if I have enough time - I can try to create PR. |
Much appreciated, good luck. Any questions - feel free to ask. |
When i try to run tests - i get:
module.js:340 Error: Cannot find module './JSON-Schema-Test-Suite/remotes/integer.json' |
You need |
Thanks. schema:
data:
Code
|
I don't see all the code/error stack. Is it compile time or validation time, what is the line/code that triggers the error? What I see wrong in the snippet (not related to the error) is that it assumes it is always possible to coerce type. But depending on data type it may not be possible to coerce it and if it isn't it should still create Also you won't be able to coerce type on the top level of data as there is no parent data to update, so in case it's top level it should simply fail validation . But I guess it's work in progress... |
Full error message:
|
changed file validate.jst from line 104 to 115 |
Looks like {{= $passData}} evaluetes to value of field, not to field name as i thinked... |
:) |
How get variable name to rewrite it value?
but when i use array or object... |
you need a previous level data + current property which is something like On the root level (Edited: |
The original idea was indeed to replace the string property with the correctly typed value…
|
not sure I follow |
I'm commenting on this:
What I had in mind was that values either match the schema or need to be coerced to match the schema to pass validation. If it cannot be coerced for whatever reason it shouldn't pass validation. Just my $0.02. It sounds like another way of getting around the level 0 shortcoming you're referring to above might be to shift everything down one level - e.g. wrap the current level 0 in an object. This would no doubt require a bigger change but should allow you to coerce level 0 properties. Just thinking aloud. |
level 0 is the data passed to validate function. For example the schema is If data passed to validate is an object then its properties are level 1 already. |
Btw, maybe you should be able to coerce array to object (together with length property), and object to array (if all properties are strings of numbers). But again, if it's a top level object/array, the caller won't see the change. But maybe it's overkill... |
Thanks @epoberezkin that case makes perfect sense. However I would want validation to fail bc we cannot change the data we cannot coerce to make the input match the schema.
Another thought occurs to me as well... just as we have 'validate.errors' we could build a coerced object that might be accessible in 'validate.coerced' or 'validate.data'. In this way we could support coercion of primitives as well as objects as you suggest (at level-0)... but it would have to be understood that for primitives the top level value cannot change. Then that actual increment line of code would look like:
I don't love it by the way... but it might be a clever work-around if people needed coercion for level 0 primitives. Thoughts?
I definitely agree it could be used beyond strings... it just felt like the simplest 90% solution to my problem. By the way - my use case doesn't require the level-0 stuff you're talking about above. I'm perfectly happy to always pass in objects. I'm just continuing the discussion bc I realize this only makes sense for you if it's a clean general solution. |
Ok, thanks I think collecting "coercions" is a bit overkill, too much code for something of limited use... Top level is a theoretic case, usually objects/arrays are validated, but for consistency it is better to coerce it even though it won't be returned to caller. Also easier to test coercions. object <-> array coercion is also a bit too much. What should be coerced I think should be similar (but not exactly the same) to what JS coerces:
|
As usual, everything is more complex than it seems on the surface |
@epoberezkin +1 - Yes - you've nailed it. The one thing that felt like we might disagree on was that I'd suggest that we don't allow coercion at the top level to indicate a pass. Rationale: the framework cannot 'correct'/coerce primitives (level-0) - therefore 'validate(data)' should be false unless type is already correct if any level-0 properties are of the wrong type. Comments on that bit? |
Actually on second read - a couple questions:
Why bother with this one? Is null a type or a value? Does it hold special significance in the framework? IMHO null is a valid value for any type - though I guess I'm not sure how this is handled in the JSON schema... so maybe this is a stupid question.
I do like the idea of '' <-> null. |
"null" is a type in JSON-schema standard, so it can be coerced to if the schema has { type: "null" } By the way, the whole thing gets complicated by the fact that there can be multiple types in So null value won't be valid for any type of data, unless you use, e.g., And only coerce if it matches none of the types... omg |
Gotcha wrt null... I still think 0 is not null... That said - I could see the case for '' - that's what I'd be faced with using this with a form most likely. I think you're right... coerce in order sounds like a very reasonable approach. |
JavaScript thinks it shouldn't coerce... English thinks it's the same... I think it's either nothing should coerce to null (like in JavaScript) or all of the above. But if you try to stay closer to JavaScript then |
I'm looking at this through the lens of using it in web forms where I'll primarily be getting string data back. In that case - for the most part I'll be dealing with strings. This feature will be of no use to me without the basic string conversions you've laid out for boolean, number, integer and primitives in general. And within that context
I struggle a bit more with this in a numeric sense:
It's self-centered but bc I don't see a use case for it... I simply wouldn't implement it. As mentioned I could see many more use cases but I would forestall implementing those types of things until there was a clear story for them. |
how we can coerce array? |
Please don't coerce array. |
Yes, i mean some schema like that:
We can coerce if array have one type of values. but can't if several
->
|
validate.jst generates code for all subschemas, why do you need to worry about arrays in particular? |
Because in arrays order of types is not guaranteed
data can be
and we don't know how cast this types |
If the schema is as above, the first subschema applies to the 1st item only, and so on. validate.jst will be executed once for each subschema to generate code for each of them. So for the first item it has to cast to integer, but data matches already; for the second - from string to boolean, for the third - from boolean to string. So what is the problem? |
My mistake - i thinked that array in types is equal items: { oneOf: [...] } |
The problem of multiple types exists though if types keyword is an array. In this case you have to match if data matches any of them and if not try to coerce in order (see above). oneOf issue I would simply disregard, if each schema in oneOf has type there potentially will be multiple coercions but given that they are all reversible I don't see it as a problem. Although depending on coercion rules string value may change after it's coerced to boolean and back for example... @darrin oneOf/etc. with different types in subschemas is another reason (in addition to having a generic solution) to implement coercions for all scalar types and not just for strings. And probably they should be one-to-one relationships so that coercing to any type and back does not change the value. |
Looks like I overestimated myself. It was too difficult for me... |
No problem. |
So I'll do it then |
In 3.4.0 |
Super! You are awesome! |
:) |
Hi there -
Thanks so much for writing this fantastic validator!
I'm using it for POSTed forms with checkboxes and other cases where basically I'd love to support conversion to a different type from a string and (as long as conversion from string works) changing the object in place, allowing validation to continue without errors.
I realize this is a corruption of pure validation and there would be a performance hit but I suspect there are others out there that would like coercion to work as well. An option to 'allowTypeCoercion' or 'laxMode' could allow transformation of primitives like integers, floats and boolean when a 'string' is found.
In the absence of support for this - I'm doing validation of the request.body with string types - and then if I need them manually converting each string to a primitive or other type. Beyond requiring additional code in which there's opportunity for inconsistencies with the schema - errors are found further downstream which we need to ripple upward. Support for this via an attribute would eliminate a bunch of redundant code...
It looks like the best I can do currently is to specify a string 'format' to try to enforce a numeric value for example or perhaps an enum to enforce the string 'true', 'false' in the case of a boolean. I might be able to use keywords as described in your documentation to try to make this more consistent.
Am I missing something that would allow conversion or support this in a more elegant way? Are there others interested in this sort of thing?
Thanks in advance,
-Darrin
The text was updated successfully, but these errors were encountered: