如何在JSON API中表示无限大?

22
什么是在JSON API中表示无限的最佳方法?例如,本月可免费阅读文章(这对某些订阅会有一个有限的数字,在高级订阅上则为无限)。
在此用例中,是返回null更好呢,还是扩展JSON并使用javascript的Infinity值更合适?后者似乎更合适,但我从未见过使用此方法的API示例。
如果有人有公共Web API表示无穷大的示例,那也很酷。

2
我刚刚查了一下,null 不是一个好的实现方式,因为当你需要使用 null 作为空表示时,你会陷入困境。所以像这个答案中建议的,在处理时先将其作为字符串再进行转换是可以的。https://dev59.com/B2Qn5IYBdhLWcg3wr406 - FZE
“null” 确实听起来不是个好主意 - 像 PHP 这样的弱类型语言在某些情况下会将 “null” 转换为 “0”。 - Pekka
你能谈谈你想要表示无穷大的具体情况吗? - Ruan Mendes
很少有好主意去特别表示无穷大,可以参考下面我的回答。 - Bradley Thomas
7个回答

14

我的建议是添加一个“limit”字段,仅在确实存在限制时才存在:

当用户还剩下40个时:

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

当用户拥有无限制的访问权限时,请将其删除,表示没有任何限制:


{
    "yourdata":""
}

1
这个问题在于如果“limit”缺失,我们无法确定它是否真的是无限的,还是有一些程序错误导致它丢失了。 - Bradley Thomas
2
好的,你可以使用布尔值添加另一个字段:"isLimited":"true/false" 进行二次检查。但是你应该真正尝试制作一个可信赖的 api。如果这个字段可能出错,我就不会信任其他任何字段。 - Björn Kechel
1
这是我们在 API 中最终采取的做法,供参考。我会等到赏金期结束后再接受答案。在我们的内部使用情况中,缺少密钥会触发一个合理的默认值。然而,信任文档的完整性感觉非常奇怪。例如,我想象一下旧版本的 API 返回一个丢失的密钥。但我同意应该在不同的地方进行检查。 - Oin

8

我的建议是对于具体的值使用数字,对于理论性的值则使用字符串。我认为这样最清晰易懂。

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

然而,这似乎不是普遍的选择。在许多情况下,我看到-1nullundefined(属性不存在)表示无限制。
在VMware中,我们使用-1来指定没有限制(内存、CPU、虚拟机),使用null会有问题,因为BlazeDS将null转换为0,而0是一个有效值。

5

数字1e500被解析为无穷大Infinity


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

Or

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


1
哇,真不错!似乎实际上从1e309开始... - Mladen Mihajlovic
JSON.stringify(1e500) 返回 'null',因此它无法工作。 - Manuel Astudillo

2
Python的json库将IEEE inf值解析为Infinity:
import json

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

输出:

{"an_inf": Infinity}

Python的json库也知道如何解析这种非标准的JSON表示法:

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

输出:

{'new_sample_median': inf}

1

也许将无限制的订阅表示为完全不同的订阅类型会更好,这样您甚至不必考虑如何表示无穷大的问题。将来,您可能希望尝试基于时间而非数量的订阅,例如在一个月内无限制访问,然后您将不得不处理到期日期。

话虽如此,像1e100这样的有限但足够大的数字怎么样?如果计算一下,1e100 - 1 = 1e100,在浮点运算的有限精度下是成立的。


我认为当数字足够大时,问题在于您必须在前端处理它并显示给用户之前制定特殊规则。我猜想可以这样做:如果free_to_read < 1000: print("本月您还剩下#{free_to_read}篇文章可阅读")。但这似乎不是最理想的解决方案。 - Oin
就我个人而言,我希望能够在前端隐藏订阅的概念,以便能够从后端进行更改。您的回答意味着前端需要自行决定用户每月可以访问多少篇文章,这是基于订阅的。 - Oin
4
无论如何,你都必须处理那个问题。我不会告诉用户“您还剩无限篇文章可阅读”。 - Joni
是的,抱歉。我的意思是我必须在前端硬编码另一个数字,与后端获取的数字不同。这种情况似乎不太理想,因为需要记录前端需要查找足够大的数字(有多大?这个数字会在API的后续版本中更改吗?)并检查该数字或较低数字。 - Oin
无论您使用Infinity、null、-1或任何其他特殊值,都会遇到相同的问题。这就是为什么我的第一个建议是为不同类型的订阅设置不同的表示形式。 - Joni

0

你不能扩展JSON。好吧,你可以扩展它,但那时它就不再是JSON了。在JSON中没有表示无穷大或NaN的方法。数字有非常严格的语法规则,而无穷大或NaN不是其中的一部分。

你可以存储一个非常大的值(1e300),你可以使用字符串“Inf”或“NaN”,并确保每个处理它的人都正确处理它,或者可能使用{ "value": "Inf" },然后你可以相当确定每个人都会正确处理它或崩溃。


1
改变合法值的语义从来不是一个好主意,这只会导致混乱。 - piegames

-1

我建议使用JavaScript的Infinity值,因为它是一致的。

例如:

var x = 1;
var y = 0;

var z = x / y;

console.log(z);

// results in `Infinity`

我会说null也是另一个选择,但这可能会被误解为没有值,而Infinity实际上是一个无限可能的值。

绝对不要使用NaN。它是一个奇怪的存在,ES为此异常道歉。

以这个为例:

var x = NaN;

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

上述答案的结果是“什么?”这告诉我们NaN实际上是一种不是数字的值。

此外,它的typeof是一个number。您可以判断它是正无穷大还是负无穷大。如果您正在处理数字,请使用Infinity。它始终等于Infinity,并且将是最佳解决方案。

var x = Math.log(0);

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

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

更新

这里 - 您可以使用:

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


2
这些在 JSON 中无效,只有在 JavaScript 中有效。 - Ruan Mendes
由于ECMA262中描述的stringify()函数的设计流程提到了三个特殊的IEEE值,因此可以怀疑其意图实际上是支持IEEE754浮点数。 - iSkore
NaN和Inf不是JS特有的,它们是IEEE标准。 - iSkore
在ECMAScript中,JSON状态下省略了无穷大和NaN。 - iSkore
1
那个回答说JSON不支持无穷大??仅仅因为IEEE定义了它,并不意味着JSON使用它。 - Ruan Mendes
我知道,因此你无法对此做任何事情。我并不是说它就是这样,我是说有一些解决方法,这里提供了这些解决方法的资源。 - iSkore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接