21

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.

Oin
  • 6,951
  • 2
  • 31
  • 55
  • 2
    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. http://stackoverflow.com/questions/16644597/json-stringify-converting-infinity-to-null this – FZE Jan 24 '16 at 13:38
  • `null` indeed sounds like a bad idea - loosely typed languages like PHP will convert a `null` to `0` in some circumstances. – Pekka Jan 24 '16 at 13:39
  • Can you talk about the specific case where you want to represent infinity? – Ruan Mendes Feb 04 '16 at 15:06
  • It is rarely a good idea to make a special case to represent infinity, see my answer below. – Bradley Thomas Feb 04 '16 at 15:20

7 Answers7

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":""
}
Björn Kechel
  • 7,933
  • 3
  • 54
  • 57
  • 1
    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 missing – Bradley Thomas Feb 04 '16 at 15:22
  • 2
    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. – Björn Kechel Feb 04 '16 at 15:43
  • 1
    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. – Oin Feb 07 '16 at 18:27
7

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.

Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
5

Number 1e500 is parsed as Infinity


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

Or

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

Saif Ali Khan
  • 506
  • 4
  • 14
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.

Joni
  • 108,737
  • 14
  • 143
  • 193
  • 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. – Oin Jan 24 '16 at 13:43
  • 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. – Oin Jan 24 '16 at 13:44
  • 4
    You'll have to deal with that anyway. I wouldn't tell users "You have Infinity articles left to to read" – Joni Jan 24 '16 at 13:45
  • 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. – Oin Jan 24 '16 at 13:53
  • 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. – Joni Jan 24 '16 at 13:59
1

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}
winni2k
  • 1,460
  • 16
  • 19
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.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
-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 } }

Community
  • 1
  • 1
iSkore
  • 7,394
  • 3
  • 34
  • 59
  • 2
    Those aren't valid in JSON, only in JavaScript – Ruan Mendes Feb 04 '16 at 15:02
  • >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. – iSkore Feb 04 '16 at 15:11
  • NaN and Inf are not JS specific. They are IEEE standards – iSkore Feb 04 '16 at 15:21
  • - http://stackoverflow.com/questions/1423081/json-left-out-infinity-and-nan-json-status-in-ecmascript – iSkore Feb 04 '16 at 15:21
  • 1
    That answer says that JSON doesn't support infinity?? Just because IEEE defines it, it doesn't mean JSON uses it. – Ruan Mendes Feb 04 '16 at 15:52
  • 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. – iSkore Feb 04 '16 at 15:58