用于节点的Azure SDK在JSON响应中四舍五入

我一直在研究使用Azure SDK for node构buildREST api( https://github.com/WindowsAzure/azure-sdk-for-node )。 我在Azure表格存储中有一个简单的MessageTable – PartitionKey是一个设备标识符(消息属于特定的消息传递设备),RowKey是一个标识消息的数字。

问题是,RowKey是一个非常大的数字,通常以9的负载(这是一个“反向时间戳”)结束,当数据返回时,节点azure色的数据库将该数字向上舍入。 请参阅下面的示例JSON响应:

{ "id":"http://xxx.table.core.windows.net/MessageTable(PartitionKey='12345',RowKey='2520801590159999999')", "link":"MessageTable(PartitionKey='12345',RowKey='2520801590159999999')", "updated":"2012-03-13T15:53:34Z", "etag":"W/\"datetime'2011-11-24T13%3A36%3A41.9555578Z'\"", "PartitionKey":12345, "RowKey":2520801590160000000, "Timestamp":"2011-11-24T13:36:41.955Z", ...other results removed for brevity } 

“id”和“link”元素显示正确的RowKey 2520801590159999999; “RowKey”元素显示了一个四舍五入的版本:2520801590160000000。

任何人都知道发生了什么事?

我也logging了这个问题 – 我敢肯定,这是相同的根本原因: https : //stackoverflow.com/questions/9683515/journey-routing-fails-due-to-number-rounding

编辑@smarx:testing代码复制如下。 在运行时,转到http:// localhost:8080 / devices / 12345 / messages会得到上面采样的json输出。 Azure表是MessageTable,分区键是deviceId(12345),rowkey是messageId(2520801590159999999)。

 var express = require('express'); var http = require('http'); var azure = require('azure'); var uuid = require('node-uuid'); var tableService = azure.createTableService( '[ACCOUNT_NAME]', '[ACCOUNT_KEY]' ); var app = module.exports = express.createServer(); app.configure(function(){ app.use(app.router); }); app.configure('development', function(){ app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.configure('production', function(){ app.use(express.errorHandler()); }); app.get('/devices/:deviceId/messages', function ( req, res ) { var query = azure.TableQuery .select() .top( 30 ) .from( "MessageTable" ) .where( 'PartitionKey eq ?', req.params.deviceId ); tableService.queryEntities( query, function (error, entities) { if ( null != error ) { res.end('Could not query MessagesTable: ' + error.code); return; } res.send( entities ); }); }); app.listen(8080); console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env); 

[编辑:@smarx]:

更简单的repro:

 tableService.createTableIfNotExists('testtable', function () { tableService.insertEntity('testtable', { PartitionKey: 'pkey', RowKey: '2520801590159999999' }, function () { tableService.queryEntity('testtable', 'pkey', '2520801590159999999', function (error, entity) { console.log(entity.RowKey); // prints 2520801590160000000 }); }); }); 

这是一个bug: https : //github.com/WindowsAzure/azure-sdk-for-node/blob/master/lib/util/atomhandler.js 。

parse (默认情况下)的实现尝试猜测属性值的types,如果没有指定,我不相信是正确的行为。 (缺less一个types意味着使用默认值,即string。)

我已经提交了一个错误( https://github.com/WindowsAzure/azure-sdk-for-node/issues/114 ),包括一个build议的修复。 你可以自己尝试,只需在parse函数的顶部添加convertTypes = false

编辑 :这现在已经在回购修复。 (点击上面的GitHub问题链接来查看。)

JavaScript规定这些数字使用IEEE-754浮点格式 。 简单的答案是,它可以表示精确到15位左右的整数,但是你的数字更长,所以它被四舍五入到最接近的表示数。 (长答案涉及用于指数的位数的解释,但具有相同的结果。)

这听起来像节点azure应该使用string,而不是数字…