JSON 中的大整数被 Angular 而不是 CURL 损坏?
Posted
技术标签:
【中文标题】JSON 中的大整数被 Angular 而不是 CURL 损坏?【英文标题】:Big Integer in JSON getting corrupted by Angular but not by CURL? 【发布时间】:2016-10-19 20:01:34 【问题描述】:我使用Django Rest Framework 创建了一个 Django REST API。
我使用 3 个不同的客户端来点击这个应用程序:
Curl(用于调试目的) Swagger 接口(用于调试目的) 我的 Angular 应用程序我有一个令人困惑的问题,即 API 返回的数据被 Swagger 和 Angular 而不是 Curl 损坏。
我的 Django 模型如下所示:
class MyModel1(CachingMixin, models.Model):
id = models.BigIntegerField(default=make_id, primary_key=True)
name = models.CharField(max_length=50, null=False, blank=False,)
上面引用的make_id()
方法描述为here。我最近从标准 Django 分配和自动递增的主键实现了这一更改。作为该更改的一部分,我将 id 从 IntegerField
转换为 BigIntegerField
。
我还有一些其他的 Django 视图代码(我没有在这里显示)创建一个名为 GetMyModel1ByName
的端点。该端点返回MyModel1
的序列化实例。这是显示当我到达那个端点时会发生什么的卷曲。效果很好:
$ curl http://localhost:4212/api/getMyModel1ByName/?name=my-name
"id": 10150133855458395, "name": "my-name"
现在,当我从 Chrome 的开发者控制台点击相同的端点时会发生什么:
> $http = angular.element(document.body).injector().get('$http');
> $http.get("http://localhost:4212/api/getMyModel1ByName/?name=my-name").then(function(response) console.log(JSON.stringify(response.data)) ).catch(function (error) console.log(error.data) );
"id":10150133855458396, "name":"my-name"
您可以看到 curl 将 ID 报告为 10150133855458395。这是正确的。这就是数据库中的内容。然而 Angular 将其报告为 10150133855458396。最后一个数字是错误的。差别是1。很惊喜!
这是一个真正令人困惑的错误。我的 Django 代码非常简单,我非常确信其中没有错误。相反,我觉得将id
字段从IntegerField
更改为BigIntegerField
可能会导致此问题。为什么会发生,解决方案是什么?它破坏了我的应用程序的功能。当我通过 Swagger 访问此端点时,我看到了同样的损坏。
编辑: 另一个提问者遇到了同样的问题。很高兴知道我不是唯一一个!然而,关于这个问题的答案并不是真正的答案。他们没有解释原因。他们没有告诉我应该如何解决我的 Angular JS 代码中的问题。
【问题讨论】:
JsonResponse from Django - Incorrect values displayed的可能重复 @middlestump 谢谢!这个问题和我的差不多。很高兴知道我并不孤单。但是那里没有解决我的问题的实际答案。 如果您只是通过浏览器访问http://localhost:4212/api/getMyModel1ByName/?name=my-name
会怎样?同样的错误?如果您再次尝试 Angular 代码但取出 JSON.stringify
怎么办?
@jDo,删除 JSON.stringify 没有任何区别。
@rfkortekaas 这与 python 无关。这纯粹是客户端。
【参考方案1】:
您正在尝试存储的数字大于安全的最大 javascript 整数 value(+/- 9007199254740991)
。
您的 make_id
生成器应返回与 javascript 限制相关的值。
更多信息请阅读: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html
【讨论】:
OP 在 cmets 中写道 “当我通过浏览器(Chrome 或 Firefox)简单地访问 localhost:4212/api/getMyModel1ByName/?name=my-name 时,我得到了损坏的ID:"id":10150133855458396, "name":"my-name"
"这不是说即使不涉及JavaScript,ID也是错误的吗?
curl 是您可以信任的唯一来源。所有浏览器表示都可以使用 javascript。
确实如此。 curl 和 wget 比任何浏览器都更值得信赖。我只是不希望浏览器在不主动请求(通过编码)的情况下将响应解析为 JSON。无论如何,这可能是这里发生的事情 - 可能是通过扩展/附加组件或一些内置的浏览器魔术自动尝试转换数值和溢出。 ID 应该是一个字符串开头。
是的!另见类似问题:***.com/questions/1379934/…【参考方案2】:
TLDR
长话短说。让您的视图将响应作为字符串返回。
"id": "10150133855458395", "name": "我的名字"
长篇大论
让我们缩小范围。事实上,你可以而且应该在没有 django 参与的情况下进行测试。请将您从curl http://localhost:4212/api/getMyModel1ByName/?name=my-name
获得的 json 保存到您的 django 项目的 /static/ 文件夹中。现在,当您获取它时,django 不再参与图片。您甚至可以将此文件托管在其他类型的服务器上。我们称之为 hello.json
现在如果你输入http://localhost:4212/static/hello.json
,你应该会得到。
"id": 10150133855458395, "name": "my-name"
更新:
如果您没有正确看到 JSON 数据,则表示您遇到了Q&A in the first comment 中描述的问题。你有一个狡猾的扩展,它弄乱了 JSON。禁用所有扩展,然后重试。一一启用。
现在让我们创建一个小角度脚本。
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<h1>myjson</h1>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http)
$http.get("/static/hello.json")
.then(function(response)
console.log(response.data)
$scope.myjson = response.data;
);
);
</script>
</body>
</html>
然后将其保存为 angular.html
在您的静态文件夹中,您可以在浏览器中将其加载为 http://localhost:4212/static/angular.html 显示。
"id":10150133855458396,"name":"my-name"
这绝对不是正确的结果。但是没有BigIntegerField
,这里也没有django。问题完全在于浏览器和角度。我们设法缩小了问题的范围。从浏览器检索的响应中可以看出,它完全在角度范围内。
Angular 对大量数据感到窒息。而是将它们作为字符串发送。
【讨论】:
令人窒息的并不是太多的棱角。它是 JavaScript。它没有单独的整数类型。它只有一个 Number 类型,它存储为浮点值。 谢谢。我会尽快实施。假设它有效,我会标记它正确,我会标记这个答案正确。 很遗憾,浏览器/Javascript/Angular 在处理无法识别的大整数时没有抛出错误或警告。以上是关于JSON 中的大整数被 Angular 而不是 CURL 损坏?的主要内容,如果未能解决你的问题,请参考以下文章