Search code examples
javascriptjsonbase64decodeencode

convert base64 to json in javaScript


For example, I have a base64 code like this

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="

Now I want to convert this to json

I have tried to convert this base64 to object But I don't know if it's true or not but still my problem is not solved because I can't do anything with that 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="

Convert to string using atob

let convertString = atob(base64);

Convert string to 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);
}

Now, using the pako library, it becomes an array that contains an object, but there is a space between all the characters, and this is very strange.

let inflatedData = pako.inflate(uint8Array, { to: 'string' });
console.log(inflatedData)

This is the image of the inflatedData console output

enter image description here

A point that might help: the data that comes from the database is typed as varBinary(Max).


Solution

  • This string is a little funky. It's JSON in UTF16-LE, gzipped, then base64 encoded. In Node:

    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="
    
    const zlib = require('zlib') // the builtin, not the old npm package
    const buf = Buffer.from(base64, 'base64')
    const res = zlib.gunzipSync(buf).toString('utf16le')
    
    console.log(JSON.parse(res))
    

    The result is an array of objects that look like test data.


    Per the comments, here's how it could work in the browser. This assumes pako, which is mentioned in the question:

    import pako from 'pako'
    const gzipped = atob(base64)
    
    const toU = (d) =>
        new Uint8Array([...d]
            .map((c) => c.charCodeAt(0)))
    
    const utf16 = pako.inflate(toU(gzipped), { to: 'string' })
    const td = new TextDecoder('utf-16le')
    const res = td.decode(toU(utf16))
    
    console.log(JSON.parse(res))
    

    There might be a more efficient way to do this, but it's very late, so I'm not able to see it right now.