0

在 javascript(不使用节点)上,当使用库( https://github.com/paroga/cbor-js)和在线使用 CBOR(https://cbor.me/ )进行 CBOR 编码时,我面临不同的结果。请注意,即使使用更新的 CBOR 库,结果也是相同的。

例如设置一个对象,例如:

const initial = { 1: "John", "-2": 456 };

使用 CBOR 在线编码给出:a201644a6f686e622d321901c8。详情如下:

A2             # map(2)
   01          # unsigned(1)
   64          # text(4)
      4A6F686E # "John"
   62          # text(2)
      2D32     # "-2"
   19 01C8     # unsigned(456)

现在在 javascript 上使用 CBOR 库进行编码会产生不同的结果:a26131644a6f686e622d321901c8

在在线 CBOR 上解码以上十六进制时,我得到:{“1”:“John”,“-2”:456}。结果几乎与常量 'initial' 相同,只是键 1 现在带有引号 (")。

CBOR online 将我的十六进制值重新格式化为更“可读”的视图:

A2             # map(2)
   61          # text(1)
      31       # "1"
   64          # text(4)
      4A6F686E # "John"
   62          # text(2)
      2D32     # "-2"
   19 01C8     # unsigned(456)

请参阅下面我的 Javascript 代码:

    //convert an array of bytes (as 8 bits) to string of Hex. ensure that Hex value are not return with 1 digit but 2 digits. ie '01' instead of '1'
    function toHexString(byteArray) {
      var s = '';
      byteArray.forEach(function(byte) {
        s += ('0' + (byte & 0xFF).toString(16)).slice(-2);
      });
      return s;
    }

    const initial = { 1: "John", "-2": 456 };
    
    var encoded = CBOR.encode(initial);
    var encodedHex = toHexString(Array.from(new Uint8Array(encoded)));
    console.log ( encodedHex );

我可以手动替换特定的十六进制值,例如:

'61 31 64' 替换为 '01 64'

但不要想这样做,因为列表对于涵盖所有可能的选项可能很重要。

是否有人有解决方法,因为我需要我的结果是 'a201644a6f686e622d321901c8' 而不是 'a26131644a6f686e622d321901c8' ?

4

1 回答 1

0

Javascript 中的对象键

CBOR规范第 5.6 节说:

在需要与基于 JSON 的应用程序交互的应用程序中,通过将键限制为仅文本字符串来简化转换

实际上,cbor-js包使用了这里Object.keys的方法,它将所有键作为字符串返回。Javascript 不区分数字及其字符串值并将其视为(而cbor.me将其视为具有两个条目的映射)。{'1':1, 1:2}{'1':2}

修改后的解决方案cbor-js

您的示例表明您希望CBOR 将非负数字键视为数字。这可以通过cbor-js源代码上的以下补丁来实现:

diff --git a/cbor.js b/cbor.js
--- a/cbor.js
+++ b/cbor.js
@@ -164,7 +164,10 @@ function encode(value) {
           writeTypeAndLength(5, length);
           for (i = 0; i < length; ++i) {
             var key = keys[i];
-            encodeItem(key);
+            if (isNaN(key) || Number(key) < 0)
+              encodeItem(key);
+            else
+              encodeItem(Number(key));
             encodeItem(value[key]);
           }
         }

有了这个改变,Node.js 给了我

> Buffer.from(cbor.encode({1:'John','-2':456})).toString('hex'))
'a201644a6f686e622d321901c8'

或者,您甚至可以通过省略 || Number(key) < 0上面补丁中的 来将负数字键视为数字。这给

> Buffer.from(cbor.encode({1:'John','-2':456})).toString('hex'))
'a201644a6f686e211901c8'
A2             # map(2)
   01          # unsigned(1)
   64          # text(4)
      4A6F686E # "John"
   21          # negative(1)
   19 01C8     # unsigned(456)

解决方案cbor

与 不同cbor-js的是,该cbor包允许您对 Javascript 进行编码Map,该 Javascript 将数字键与字符串键区分开来:

> Buffer.from(cbor.encode(new Map().set(1,'John').set(-2,456))).toString('hex')
'a201644a6f686e211901c8'
于 2021-12-17T16:12:39.457 回答