JSON对象的大小是多少?(以KB / MB为单位)

66

我怎样知道通过网络传输的数据量,以KB、MB为单位表示大小?

举个例子:

{
  'a': 1,
  'b': 2
}

我如何确定这个载荷的大小,而不是对象中的长度或项目。

更新

content-encoding:gzip
content-type:application/json
Transfer-Encoding:chunked
vary:Accept-Encoding

2
取决于你的编码方式,它是什么? - Qantas 94 Heavy
还要看你的Web服务器是否自动压缩响应... - Taj Morton
还取决于压缩,gzip 在传输 json 数据时非常常见。 - Alex Wayne
这里仍然几乎没有任何细节。你是如何传输JSON的?你的代码在哪里?如果你自己将其作为字符串传递(而不是某个库对其进行序列化),那么只需在应用下面答案中描述的Unicode技巧后计算字符串中字符的数量即可。 - Lightness Races in Orbit
5个回答

107

回答实际问题的应该包括头部消耗的字节数,并考虑gzip压缩,但我将忽略这些内容。

你有几个选择。它们在运行时都会输出相同的答案:

如果使用浏览器或Node(不是IE)

const size = new TextEncoder().encode(JSON.stringify(obj)).length
const kiloBytes = size / 1024;
const megaBytes = kiloBytes / 1024;

如果需要在IE上运行,请使用polyfill

如果使用Node

const size = Buffer.byteLength(JSON.stringify(obj))

(这与 Buffer.byteLength(JSON.stringify(obj)," utf8 ") 相同)。

适用于IE、现代浏览器和Node的快速方式

const size = encodeURI(JSON.stringify(obj)).split(/%..|./).length - 1;

最后一个解决方案在几乎所有情况下都适用,但如果您提供包含不应存在的字符串的输入,例如let obj = { partOfAnEmoji: ""[1] },那么该解决方案将抛出一个URIError: URI malformed异常。我提供的另外两个解决方案就没有这个弱点。

(致谢:第一种解决方案的功劳归于这里。 第二种解决方案的功劳归于utf8-byte-length包(很好,您可以使用它)。 大部分最后一个解决方案的功劳归于这里,但我对其进行了一些简化。 在研究此问题时,我发现了utf8-byte-length包的测试套件非常有帮助。)


22

对于ASCII码,如果您想统计字符数量,可以使用以下代码:

JSON.stringify({
  'a': 1,
  'b': 2
}).length

如果您也有特殊字符,可以通过一个计算UTF-8字符长度的函数来处理...

function lengthInUtf8Bytes(str) {
  // Matches only the 10.. bytes that are non-initial characters in a multi-byte sequence.
  var m = encodeURIComponent(str).match(/%[89ABab]/g);
  return str.length + (m ? m.length : 0);
}

Should be accurate...

var myJson = JSON.stringify({
  'a': 1,
  'b': 2,
  'c': 'Máybë itß nºt that sîmple, though.'
})

// simply measuring character length of string is not enough...
console.log("Inaccurate for non ascii chars: "+myJson.length)

// pass it through UTF-8 length function...
console.log("Accurate for non ascii chars: "+ lengthInUtf8Bytes(myJson))

/* Should echo...

Inaccurate for non ascii chars: 54
Accurate for non ascii chars: 59

*/

工作演示


35
也许事情并没有那么简单。 - Alex Wayne
1
@AlexWayne 你可以结合类似这样的东西:https://dev59.com/gW035IYBdhLWcg3wSN4G#5515960 - Billy Moon
1
如果您将此乘以8,则应该获得ASCII字符串的字节数。为什么要乘以8? - Lightness Races in Orbit
@LightnessRacesinOrbit 因为现在已经很晚了 :) - Billy Moon
2
@BillyMoon:你的意思是……因为现在已经很晚了吗?;) - Lightness Races in Orbit
这会导致 lengthInUtf8Bytes("") 的答案不准确。它应该输出 4,但它输出了 5 - davidbludlow

20

这里有一个完成任务的函数。

function memorySizeOf(obj) {
    var bytes = 0;

    function sizeOf(obj) {
        if(obj !== null && obj !== undefined) {
            switch(typeof obj) {
            case 'number':
                bytes += 8;
                break;
            case 'string':
                bytes += obj.length * 2;
                break;
            case 'boolean':
                bytes += 4;
                break;
            case 'object':
                var objClass = Object.prototype.toString.call(obj).slice(8, -1);
                if(objClass === 'Object' || objClass === 'Array') {
                    for(var key in obj) {
                        if(!obj.hasOwnProperty(key)) continue;
                        sizeOf(obj[key]);
                    }
                } else bytes += obj.toString().length * 2;
                break;
            }
        }
        return bytes;
    };

    function formatByteSize(bytes) {
        if(bytes < 1024) return bytes + " bytes";
        else if(bytes < 1048576) return(bytes / 1024).toFixed(3) + " KiB";
        else if(bytes < 1073741824) return(bytes / 1048576).toFixed(3) + " MiB";
        else return(bytes / 1073741824).toFixed(3) + " GiB";
    };

    return formatByteSize(sizeOf(obj));
};

console.log(memorySizeOf({"name": "john"}));

我从以下网址获取了代码片段:

https://gist.github.com/zensh/4975495


不准确。即使对于utf8也会给出更高的数字。 - ZuzEL

2

Buffer.from(JSON.stringify(obj)).length会给你字节数。


0

JSON对象是JavaScript对象,this SO question已经展示了一种计算大致大小的方法。 <- 请查看评论/编辑

编辑:你实际的问题相当困难,因为即使你可以访问头部,据我所知,内容大小也不会显示gzip值。

如果你足够幸运拥有一个好的HTML5浏览器,this包含了一段很好的代码:

var xhr = new window.XMLHttpRequest();
   //Upload progress
   xhr.upload.addEventListener("progress", function(evt){
   if (evt.lengthComputable) {
     var percentComplete = evt.loaded / evt.total;
     //Do something with upload progress
     console.log(percentComplete);
     }
   }

因此,以下内容应该可以正常工作(目前无法测试):

var xhr = new window.XMLHttpRequest();
if (xhr.lengthComputable) {
  alert(xhr.total);
}

请注意,XMLHttpRequest是本地的,不需要jQuery。
接下来编辑:
我发现一个有点重复(略有不同的问题,基本相同的答案)。对于这个问题来说,重要的部分是:
content_length = jqXHR.getResponseHeader("X-Content-Length");

这里的 jqXHR 是你的 XmlHttpRequest。


请勿在您的答案中简单地链接到另一个答案。如果您认为这个问题是另一个问题的副本,请标记它。 - Andrew Marshall
1
我的声望还不够高:/ - Sebb
2
不,JSON对象并不是JavaScript对象。你链接的答案之所以错误,是因为它没有尝试计算词法(字符串)表示中的字节数。 - Lightness Races in Orbit
@Sebb,您的声誉足以标记。 - Andrew Marshall

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