JavaScript中Base64转JSON遇字符间隔问题求助
问题描述
我有一段如下的Base64编码,希望将其转换为可用的JSON,但尝试后无法正常使用转换后的结果:
const base64 = "H4sIAAAAAAAEAO2b0W6CMBSGz6MsXm+JUKi6N9gzLLsw4jYTo0bJbpa9+44Ig0J7kBW0PSENNG2B9vtjw09PfYVvmMAGEjw/QwiPmKdYTmEL66xuAics7eGI5QcI4AmPSXbdAZZZ7Q7bX/InBFlLeYdaf37mFx7bSl2C5ROs8OoNPvHc9x6feOk5BAFR3tsK65O/MQmQEGP+g21VAgFzI8O5hx183Gz0zT5VBrW9SbLwkiTQsEQw9ZQl1NKY54nrNJf51CQS7IgidkQxOyLJjmjGjsjP9ylF5Ot71UQUe/x2NREFzIgkO88g2XkGyc4zSHaeQXrqGUTOVD3r+Xx0ECpXF1rKXaj382OnfMi92dX+h1ViZvAvByUtG+lYS+ta2ikpraX7qLnEcgLveX4530Jhyk+V95cjK/N7//76UEylovXTqUd5t1G9NvUonziq16Ye5UlH9drUo/zvqF6bepTXHtWj1Ztf6W3/q16x6nOdfqGH+l3nj0f9TPoNO3sj9vpRX+Kjfu36Detcivg4X/2G9S789Rv2q63YacJXv2G/27jrZ1avupcqJBQKe9WnWBtqcoss8qGPw9lErfodf1+RRZuolZtENlErN4lsolZuEtlErdwksolTuUlks9PFTSKbnS4uEkmrnS5uEtnsdHGRaE4S2fvG/pldco2LgVe9RAf1xA3UW8Entm6zUdS1CHC26+e7mW/R6as2aiXUjVk/UupXH2f7KNvXw6ed1oRi6xkd5f+heINfmSW/7QgyAAA="
补充说明:该数据来自SQL Server数据库,类型为varBinary(Max)。
已尝试步骤
- 使用
atob转换为字符串:let convertString = atob(base64); - 将字符串转换为
ArrayBuffer:let arrayBuffer = new ArrayBuffer(convertString.length); let uint8Array = new Uint8Array(arrayBuffer); for (let i = 0; i < convertString.length; i++) { uint8Array[i] = convertString.charCodeAt(i); } - 使用pako库解压后,得到的字符间存在空格,无法正常解析为JSON:
let inflatedData = pako.inflate(uint8Array, { to: 'string' }); console.log(inflatedData)
解决方法
问题出在解压后的原始字节采用UTF-16LE编码(SQL Server的varBinary(Max)存储Unicode字符串时,通常用UTF-16LE格式),但pako默认以UTF-8解码,导致字符被错误解析,出现间隔空格。
正确处理步骤如下:
解码Base64到Uint8Array(可使用更简洁的写法):
const uint8Array = Uint8Array.from(atob(base64), c => c.charCodeAt(0));用pako解压获取原始字节数组:
不要直接指定to: 'string',先获取解压后的Uint8Array:const decompressedBytes = pako.inflate(uint8Array);用UTF-16LE编码解码字节数组为字符串:
使用TextDecoder指定编码格式,将解压后的字节转换为正确的字符串:const decoder = new TextDecoder('utf-16le'); const jsonString = decoder.decode(decompressedBytes);解析为JSON对象:
const jsonData = JSON.parse(jsonString); console.log(jsonData);
完整代码示例:
const base64 = "H4sIAAAAAAAEAO2b0W6CMBSGz6MsXm+JUKi6N9gzLLsw4jYTo0bJbpa9+44Ig0J7kBW0PSENNG2B9vtjw09PfYVvmMAGEjw/QwiPmKdYTmEL66xuAics7eGI5QcI4AmPSXbdAZZZ7Q7bX/InBFlLeYdaf37mFx7bSl2C5ROs8OoNPvHc9x6feOk5BAFR3tsK65O/MQmQEGP+g21VAgFzI8O5hx183Gz0zT5VBrW9SbLwkiTQsEQw9ZQl1NKY54nrNJf51CQS7IgidkQxOyLJjmjGjsjP9ylF5Ot71UQUe/x2NREFzIgkO88g2XkGyc4zSHaeQXrqGUTOVD3r+Xx0ECpXF1rKXaj382OnfMi92dX+h1ViZvAvByUtG+lYS+ta2ikpraX7qLnEcgLveX4530Jhyk+V95cjK/N7//76UEylovXTqUd5t1G9NvUonziq16Ye5UlH9drUo/zvqF6bepTXHtWj1Ztf6W3/q16x6nOdfqGH+l3nj0f9TPoNO3sj9vpRX+Kjfu36Detcivg4X/2G9S789Rv2q63YacJXv2G/27jrZ1avupcqJBQKe9WnWBtqcoss8qGPw9lErfodf1+RRZuolZtENlErN4lsolZuEtlErdwksolTuUlks9PFTSKbnS4uEkmrnS5uEtnsdHGRaE4S2fvG/pldco2LgVe9RAf1xA3UW8Entm6zUdS1CHC26+e7mW/R6as2aiXUjVk/UupXH2f7KNvXw6ed1oRi6xkd5f+heINfmSW/7QgyAAA="; // 解码Base64到Uint8Array const uint8Array = Uint8Array.from(atob(base64), c => c.charCodeAt(0)); // pako解压获取原始字节 const decompressedBytes = pako.inflate(uint8Array); // UTF-16LE解码为字符串 const decoder = new TextDecoder('utf-16le'); const jsonString = decoder.decode(decompressedBytes); // 解析为JSON const jsonData = JSON.parse(jsonString); console.log(jsonData);
错误原因说明
pako.inflate(..., { to: 'string' })默认使用UTF-8解码字节,但原始数据是UTF-16LE编码(每个字符占2字节)。UTF-8解析时会把每个字节当成独立字符,导致原本的单字符被拆成两个,表现为字符间的空格(实际是错误编码的不可见字符)。
内容的提问来源于stack exchange,提问作者davood beheshti
相关产品推荐
相关产品推荐

