How do you represent infinity in a JSON API?
Asked Answered
B

7

25

What is the best way to represent infinity in a JSON API? e.g. free to read articles for this month (this will be a finite number on some subscriptions and infinite on the premium subscription).

Is it a better idea to return null for this use case or to extend JSON and use the javascript's Infinity value? The latter seems more appropriate, but I've never seen an example of an API which does this.

It would also be cool if anyone had any examples of public Web APIs which represent infinity.

Bukavu answered 24/1, 2016 at 13:29 Comment(4)
I just checked around, null would not be the good implementation, because null already have a meaning when you need to use null for null representation you going to be stucked. So like in this answer using as string then converting while processing it would be fine. #16645097 thisOverbearing
null indeed sounds like a bad idea - loosely typed languages like PHP will convert a null to 0 in some circumstances.Pieplant
Can you talk about the specific case where you want to represent infinity?Rowdyism
It is rarely a good idea to make a special case to represent infinity, see my answer below.Xanthippe
C
14

I would include a field "limit", which only exists when there really is a limit:

when the user has 40 left:

{
    "yourdata":"",
    "limit": 40
}

when the user has unlimited access remove it, meaning there is no limit:

{
    "yourdata":""
}
Cannonry answered 4/2, 2016 at 14:43 Comment(3)
This has the problem that if "limit" is missing, we don't know if it's really unlimited or if there is some program error causing it to be missingXanthippe
ok, you could add another field using boolean: "isLimited":"true/false" to double check. but you should really try to make an api that you can trust. If this field can be erroneous, I would not trust any other field.Aminta
This is what we ended up doing in our API, FWIW. I'll wait until the bounty period is over to accept the answer. In our internal use case, a sane default is triggered by the lack of the key. It feels really strange however to trust the integrity of the document. I'm imagining an old version of the API returning a missing key for example. But I agree that that should be checked in a different place.Bukavu
R
9

My suggestion is use numbers for specific values and strings for theoretical values. I think it's clearest.

{
  "shoes": 89,
  "cars": "infinity",
  "myBankAccount": "negative-infinity"
}

However, that doesn't seem to be the popular choice. I've seen -1,null, and undefined (absence of the property) mean unlimited in many cases.

At VMware, we use -1 to specify that there are no limits (memory, CPU, VMs) and we have had problems with using null because BlazeDS converted null to 0, and 0 was a valid value.

Rowdyism answered 4/2, 2016 at 15:3 Comment(0)
B
5

Number 1e500 is parsed as Infinity


console.log(1e500); // Gives Infinity

Or

JSON.parse('{"number": 1e500}'); // Gives {number: Infinity}

Beckon answered 6/11, 2020 at 16:20 Comment(2)
Wow, really nice one! Seems to actually start from 1e309...Cabrales
JSON.stringify(1e500) gives 'null' so it does not work.Delfeena
A
2

Python's json library parses an IEEE inf value as Infinity:

import json

print(json.dumps({'an_inf': float("inf") }))

output:

{"an_inf": Infinity}

The python json library also knows how to parse this non-standard json notation:

print(json.loads('{"new_sample_median": Infinity }'))

output:

{'new_sample_median': inf}
Arlenarlena answered 20/4, 2023 at 16:14 Comment(0)
H
1

Probably it will be better to represent unlimited subscriptions as a totally different type of subscription, so you don't even have the problem of how to represent infinity. In the future you may want to experiment with subscriptions that are based on time rather than number, e.g. unlimited access during a month, and then you'll have to deal with an expriry date.

That said, wouldn't a finite but sufficiently large number such as 1e100 do? If you do the math, 1e100 - 1 = 1e100 in the limited precision of floating point arithmetic.

Hoon answered 24/1, 2016 at 13:39 Comment(5)
I think the problem with a sufficiently large number is that you would have to have special rules on the frontend for processing it before displaying to the user. I guess something like: if free_to_read < 1000: print ("You have #{free_to_read} articles left this month"). This seems less than ideal.Bukavu
FWIW I would like to hide the concept of subscriptions from the frontend in order to be able to change them from the backend. Your answer implies that frontend would need to decide on its own how many articles per month the user has access to based on the subscription.Bukavu
You'll have to deal with that anyway. I wouldn't tell users "You have Infinity articles left to to read"Hoon
Yes, sorry. My point was that I would have to hardcode another number in the frontend, different than the one I get from the backend. It feels less than ideal to have to document this idea that the frontend needs to look for a sufficiently big number (how big? will this number change in later versions of the API?) and check against that or a lower number.Bukavu
You have the same problem whether you use Infinity, null, -1, or any other special value. That's why my first suggestion is to have different representations for different types of subscription.Hoon
O
0

You can't extend JSON. Well, you can extend it, but then it isn't JSON anymore. There is no way to represent Infinity or NaN in JSON. There is a very strict syntax for numbers, and Infinity or NaN is not part of it.

You could store a very large value (1e300), you could use a string "Inf" or "NaN" and make sure everyone processing it handles it correctly, or maybe use { "value": "Inf" } and then you can be quite sure that everyone either handles it correctly or crashes.

Orlop answered 4/2, 2016 at 15:3 Comment(1)
Changing the semantics of legal values is never a good idea and a recipe for guaranteed chaos.Analyzer
R
-1

I would recommend using JavaScripts Infinity value because it is consistent.

For example:

var x = 1;
var y = 0;

var z = x / y;

console.log(z);

// results in `Infinity`

I would say null is also another choice but this could be mistaken for no value where as Infinity is actually a value of endless possibility.

Definitely don't use NaN. It's a weird beast, and ES apologized for this anomaly.

Take this for example:

var x = NaN;

if (x === x) {
    console.log('Good');
} else {
    console.log('What?');
}

The above answer results in 'What?' which tells us NaN is in fact some sort of value that is not a number.

In addition, it's typeof is a number. You can tell if it is positive infinity or negative. If you are working with numbers, use Infinity. It is consistently equal to Infinity and will be the best solution.

var x = Math.log(0);

console.log(x);
console.log(typeof(x));

if (x === x) {
    console.log('yes');
}

Update

From HERE - You can use:

{ a: { is_infinity: true, value: null }, b: { is_infinity: false, value: 10 } }

Reedy answered 4/2, 2016 at 14:56 Comment(6)
Those aren't valid in JSON, only in JavaScriptRowdyism
>Since the design flow described for the stringify() function in ECMA262 does mention the three special IEEE values, one can suspect that the intention was in fact to support IEEE754 floating point numbers.Reedy
NaN and Inf are not JS specific. They are IEEE standardsReedy
- #1423581Reedy
That answer says that JSON doesn't support infinity?? Just because IEEE defines it, it doesn't mean JSON uses it.Rowdyism
I know, and therefore there is nothing you can do about it. I'm not saying it is, I am saying there are work arounds, and here are resources on those work arounds.Reedy

© 2022 - 2024 — McMap. All rights reserved.