Giter VIP home page Giter VIP logo

Comments (17)

awwright avatar awwright commented on May 12, 2024 1

Infinity and -Infinity also pass validation, even though they're not in the JSON subset of ECMAScript Numbers.

Maybe we should distinguish between Number (ECMAScript) and number (JSON)? And/or make a property to allow the more liberal ECMAScript usage.

from jsonschema.

tdegrunt avatar tdegrunt commented on May 12, 2024

Technically NAN is a number ...

typeof NaN
'number'

from jsonschema.

hazkiel avatar hazkiel commented on May 12, 2024

And technically, typeof null is 'object' but it fails jsonschema validation when you set the type property to "object".
Why not use the same logic there?

Anyway, the language is broken and Not-a-Number shouldn't be treated like a number. I hope you see the paradox.

from jsonschema.

llafuente avatar llafuente commented on May 12, 2024

@hazkiel I see the paradox

just for fun and prove the paradox.

> typeof NaN
'number'
> typeof 100
'number'
> typeof new Number()
'object'

# summary!
# NaN & 100 are number(s)
# new Number is object
# continue

> Object.prototype.toString.call(100)
'[object Number]'
> Object.prototype.toString.call(NaN)
'[object Number]'
> Object.prototype.toString.call(new Number())
'[object Number]'

# they are all numbers? Cool!

> NaN instanceof Number
false
> 100 instanceof Number
false
> var n = 100;
undefined
> n instanceof Number
false
> new Number() instanceof Number
true

# so only (new Number) is a Number instance but it's type is an object
# this is going nowhere...

> NaN.constructor === n.constructor
true
> NaN.constructor === Number.constructor
false
> n.constructor === Number.constructor
false
> (new Number()).constructor === Number.constructor
false

# so NaN and (n=100) are alike because has the same constructor.
# and (new Number) is a Number instance and it's type is an object BUT has different constructor that Number has, pretty normal

> isNaN(NaN)
true
> isNaN(100)
false
> isNaN(new Number())
false

> isFinite(NaN)
false
> isFinite(100)
true
> isFinite(new Number())
true


# just to test if something funny here :D but not.


> Array.isArray(NaN)
false
> Array.isArray(100)
false

# for sure... they are not arrays

> Number.NaN
NaN
> Number[100]
undefined

# so Nan is inside number, 100 is not

NaN means "Not a Number", but it's a number, in fact an invalid one. So validation must fail.

from jsonschema.

tdegrunt avatar tdegrunt commented on May 12, 2024

If anyone will create a pull request to fix this issue, including working tests, I'd be happy to merge it.

from jsonschema.

offero avatar offero commented on May 12, 2024

This also bit me. NaN should fail validation, but it does not.

from jsonschema.

offero avatar offero commented on May 12, 2024

#152

from jsonschema.

awwright avatar awwright commented on May 12, 2024

@offero Can you provide an example of how?

This shouldn't generally be a problem if you're using JSON.parse() since that's guaranteed to not produce NaN.

That being said, it can produce +-Infinity if you provide it a (perfectly legal) very large number:

JSON.parse('999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999') == Number.POSITIVE_INFINITY

What should we do about this case?

from jsonschema.

offero avatar offero commented on May 12, 2024

I made a PR for it.

Interesting case. I would not expect it to do so because it's not in the JSON spec. I would think that's an issue with the parse function.

from jsonschema.

offero avatar offero commented on May 12, 2024

In the case that the number is too big to represent as a 64-bit floating point value, what should JSON.parse do? I guess the authors thought it would be best to not error at that point.

from jsonschema.

offero avatar offero commented on May 12, 2024

It's actually the parseFloat implementation.

From MDN:

parseFloat can also parse and return the value Infinity. You can use the isFinite function to determine if the result is a finite number (not Infinity, -Infinity, or NaN).
> parseFloat('99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999')
Infinity

Python loads it fine:

In [1]: import json
In [2]: json.loads('99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999')
Out[2]: 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999L

And yes it does have +inf:

In [10]: float("+inf")
Out[10]: inf

from jsonschema.

awwright avatar awwright commented on May 12, 2024

@offero But what's the problem you are facing, exactly?

The problem that this issue poses is that JSON allows arbitrary precision and prohibits NaN and +- Infinity, and that this isn't exactly compatible with how ECMAScript stores numbers.

If you're getting a true JSON document (a series of bytes, application/json), you will never run into this issue, since JSON.parse does not produce NaN.

And we do wish to support implementations that wish to use a superset of JSON values -- allow schemas to specifying if NaN and Infinity, etc, is legal or not.

There's a lot of cases to account for, really.

from jsonschema.

offero avatar offero commented on May 12, 2024

My problem is javascript object validation. If you call validate on an object with a NaN or Infinity number value, it will validate without errors. I am preventing invalid objects from being processed by my library by validating them.

I agree that I would simply like to specify that NaN or +- Infinity is not allowed. That would be great, but no where in the JSON schema spec does it allow for those restrictions.

from jsonschema.

tdegrunt avatar tdegrunt commented on May 12, 2024

Hmm, I did merge 7360a23

JSON schema doesn't allow for these restrictions indeed, so after some consideration I'm inclined to take it out. Thoughts?

from jsonschema.

offero avatar offero commented on May 12, 2024

The questions are: Should validate() pass with an object with NaN or +-Infinity values? Should validate() allow values that are not specified in the JSON spec (NaN and +-Infinity are not specified)?

The major problem here is with the JSON parsing.

As pointed out above with the number converting to Infinity, there is a difference between validating the JSON text and validating the parsed object. If validation passes with +-Infinity, then we are assuming that the value from the JSON text was a number too large for Javascript to hold. That means that the text itself was valid if that assumption is valid. The caveat here is that the program that validates the object still cannot assume that I can do math with the resultant object; it still must check for +-Infinity.

The NaN value case should only ever happen in Javascript when setting values on a field, not in the text version. That means that if bad math happens and NaN is set on an object, that object will still validate. It will serialize to null, which, when read back in, is invalid (typeof null !== 'number').

from jsonschema.

awwright avatar awwright commented on May 12, 2024

Ok, re-looking at this now.

NaN isn't a legal JSON value, so how about a configurable option on how to handle it:

  • number - treat as a number (current behavior)
  • invalid - always invalid
  • null - treat same as null (which is what JSON.stringify converts NaN to)
  • undefined - treat same as undefined
  • other value - e.g. treat as zero

from jsonschema.

awwright avatar awwright commented on May 12, 2024

It looks like NaN no longer validates as a number, I'll open a new issue to deal with configuring the behavior.

See: #248

from jsonschema.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.