How to convert a JSON object to a base64 string?

16,973

Solution 1

The difference is clear if you simply reverse the base64 encoding on both results.

(atob() decodes base64, btoa() encodes it)

Amazon's example:

atob('eyAiZXhwaXJhdGlvbiI6ICIyMDEzLTA4LTA3VDEyOjAwOjAwLjAwMFoiLA0KICAiY29uZGl0aW9ucyI6IFsNCiAgICB7ImJ1Y2tldCI6ICJleGFtcGxlYnVja2V0In0sDQogICAgWyJzdGFydHMtd2l0aCIsICIka2V5IiwgInVzZXIvdXNlcjEvIl0sDQogICAgeyJhY2wiOiAicHVibGljLXJlYWQifSwNCiAgICB7InN1Y2Nlc3NfYWN0aW9uX3JlZGlyZWN0IjogImh0dHA6Ly9leGFtcGxlYnVja2V0LnMzLmFtYXpvbmF3cy5jb20vc3VjY2Vzc2Z1bF91cGxvYWQuaHRtbCJ9LA0KICAgIFsic3RhcnRzLXdpdGgiLCAiJENvbnRlbnQtVHlwZSIsICJpbWFnZS8iXSwNCiAgICB7IngtYW16LW1ldGEtdXVpZCI6ICIxNDM2NTEyMzY1MTI3NCJ9LA0KICAgIFsic3RhcnRzLXdpdGgiLCAiJHgtYW16LW1ldGEtdGFnIiwgIiJdLA0KDQogICAgeyJ4LWFtei1jcmVkZW50aWFsIjogIkFLSUFJT1NGT0ROTjdFWEFNUExFLzIwMTMwODA2L3VzLWVhc3QtMS9zMy9hd3M0X3JlcXVlc3QifSwNCiAgICB7IngtYW16LWFsZ29yaXRobSI6ICJBV1M0LUhNQUMtU0hBMjU2In0sDQogICAgeyJ4LWFtei1kYXRlIjogIjIwMTMwODA2VDAwMDAwMFoiIH0NCiAgXQ0KfQ==')
"{ "expiration": "2013-08-07T12:00:00.000Z",
  "conditions": [
    {"bucket": "examplebucket"},
    ["starts-with", "$key", "user/user1/"],
    {"acl": "public-read"},
    {"success_action_redirect": "http://examplebucket.s3.amazonaws.com/successful_upload.html"},
    ["starts-with", "$Content-Type", "image/"],
    {"x-amz-meta-uuid": "14365123651274"},
    ["starts-with", "$x-amz-meta-tag", ""],

    {"x-amz-credential": "AKIAIOSFODNN7EXAMPLE/20130806/us-east-1/s3/aws4_request"},
    {"x-amz-algorithm": "AWS4-HMAC-SHA256"},
    {"x-amz-date": "20130806T000000Z" }
  ]
}"

Your result:

atob('eyJleHBpcmF0aW9uIjoiMjAxMy0wOC0wNlQxMjowMDowMC4wMDBaIiwiY29uZGl0aW9ucyI6W3siYnVja2V0IjoiZXhhbXBsZWJ1Y2tldCJ9LFsic3RhcnRzLXdpdGgiLCIka2V5IiwidXNlci91c2VyMS8iXSx7ImFjbCI6InB1YmxpYy1yZWFkIn0seyJzdWNjZXNzX2FjdGlvbl9yZWRpcmVjdCI6Imh0dHA6Ly9hY2w2LnMzLmFtYXpvbmF3cy5jb20vc3VjY2Vzc2Z1bF91cGxvYWQuaHRtbCJ9LFsic3RhcnRzLXdpdGgiLCIkQ29udGVudC1UeXBlIiwiaW1hZ2UvIl0seyJ4LWFtei1tZXRhLXV1aWQiOiIxNDM2NTEyMzY1MTI3NCJ9LFsic3RhcnRzLXdpdGgiLCIkeC1hbXotbWV0YS10YWciLCIiXSx7IngtYW16LWNyZWRlbnRpYWwiOiJBS0lBSU9TRk9ETk43RVhBTVBMRS8yMDEzMDgwNi91cy1lYXN0LTEvczMvYXdzNF9yZXF1ZXN0In0seyJ4LWFtei1hbGdvcml0aG0iOiJBV1M0LUhNQUMtU0hBMjU2In0seyJ4LWFtei1kYXRlIjoiMjAxMzA4MDZUMDAwMDAwWiJ9XX0=')
"{"expiration":"2013-08-06T12:00:00.000Z","conditions":[{"bucket":"examplebucket"},["starts-with","$key","user/user1/"],{"acl":"public-read"},{"success_action_redirect":"http://acl6.s3.amazonaws.com/successful_upload.html"},["starts-with","$Content-Type","image/"],{"x-amz-meta-uuid":"14365123651274"},["starts-with","$x-amz-meta-tag",""],{"x-amz-credential":"AKIAIOSFODNN7EXAMPLE/20130806/us-east-1/s3/aws4_request"},{"x-amz-algorithm":"AWS4-HMAC-SHA256"},{"x-amz-date":"20130806T000000Z"}]}"

As far as I can tell, it's because JSON.stringify removes whitespace while Amazon's method is preserving it. If you wanted to, you could use JSON.stringify with some extra options to "pretty print" the output. But more likely, it doesn't matter at all - as long as the base64 encoded string decodes to valid JSON, I doubt S3 cares if it has whitespace or not. I wouldn't worry about the fact that you can't replicate Amazon's example exactly.

Solution 2

As explained in the above answer you can prettify the JSONString with few parameters. Here's the catch for your question

btoa(JSON.stringify(policy,undefined,1))

This will give you a spacing of 1

Share:
16,973
Rob Johansen
Author by

Rob Johansen

BY DAY: Full stack developer for a software consultancy. BY NIGHT: Creator of Wordit (https://wordit.app), a word game that combines the gameplay of traditional word games with a deck of cards that empower you to make every turn count. FOR FUN: Teaching my son how to play the original Super Mario Bros on NES.

Updated on June 07, 2022

Comments

  • Rob Johansen
    Rob Johansen over 1 year

    I'm attempting to follow Amazon's example of browser-based file uploads to S3 using POST.

    The example provides this JSON policy...

    { "expiration": "2013-08-06T12:00:00.000Z",
      "conditions": [
        {"bucket": "examplebucket"},
        ["starts-with", "$key", "user/user1/"],
        {"acl": "public-read"},
        {"success_action_redirect": "http://acl6.s3.amazonaws.com/successful_upload.html"},
        ["starts-with", "$Content-Type", "image/"],
        {"x-amz-meta-uuid": "14365123651274"},
        ["starts-with", "$x-amz-meta-tag", ""],
    
        {"x-amz-credential": "AKIAIOSFODNN7EXAMPLE/20130806/us-east-1/s3/aws4_request"},
        {"x-amz-algorithm": "AWS4-HMAC-SHA256"},
        {"x-amz-date": "20130806T000000Z" }
      ]
    }
    

    ...and says this is the base64 encoded version of the policy:

    eyAiZXhwaXJhdGlvbiI6ICIyMDEzLTA4LTA3VDEyOjAwOjAwLjAwMFoiLA0KICAiY29uZGl0aW9ucyI6IFsNCiAgICB7ImJ1Y2tldCI6ICJleGFtcGxlYnVja2V0In0sDQogICAgWyJzdGFydHMtd2l0aCIsICIka2V5IiwgInVzZXIvdXNlcjEvIl0sDQogICAgeyJhY2wiOiAicHVibGljLXJlYWQifSwNCiAgICB7InN1Y2Nlc3NfYWN0aW9uX3JlZGlyZWN0IjogImh0dHA6Ly9leGFtcGxlYnVja2V0LnMzLmFtYXpvbmF3cy5jb20vc3VjY2Vzc2Z1bF91cGxvYWQuaHRtbCJ9LA0KICAgIFsic3RhcnRzLXdpdGgiLCAiJENvbnRlbnQtVHlwZSIsICJpbWFnZS8iXSwNCiAgICB7IngtYW16LW1ldGEtdXVpZCI6ICIxNDM2NTEyMzY1MTI3NCJ9LA0KICAgIFsic3RhcnRzLXdpdGgiLCAiJHgtYW16LW1ldGEtdGFnIiwgIiJdLA0KDQogICAgeyJ4LWFtei1jcmVkZW50aWFsIjogIkFLSUFJT1NGT0ROTjdFWEFNUExFLzIwMTMwODA2L3VzLWVhc3QtMS9zMy9hd3M0X3JlcXVlc3QifSwNCiAgICB7IngtYW16LWFsZ29yaXRobSI6ICJBV1M0LUhNQUMtU0hBMjU2In0sDQogICAgeyJ4LWFtei1kYXRlIjogIjIwMTMwODA2VDAwMDAwMFoiIH0NCiAgXQ0KfQ==
    

    However, when I do this from the Node.js REPL...

    var policy = {
      "expiration": "2013-08-06T12:00:00.000Z",
      "conditions": [
        {"bucket": "examplebucket"},
        ["starts-with", "$key", "user/user1/"],
        {"acl": "public-read"},
        {"success_action_redirect": "http://acl6.s3.amazonaws.com/successful_upload.html"},
        ["starts-with", "$Content-Type", "image/"],
        {"x-amz-meta-uuid": "14365123651274"},
        ["starts-with", "$x-amz-meta-tag", ""],
    
        {"x-amz-credential": "AKIAIOSFODNN7EXAMPLE/20130806/us-east-1/s3/aws4_request"},
        {"x-amz-algorithm": "AWS4-HMAC-SHA256"},
        {"x-amz-date": "20130806T000000Z" }
      ]
    };
    
    console.log(new Buffer(JSON.stringify(policy)).toString('base64'));
    

    ...I get a different base64 string:

    eyJleHBpcmF0aW9uIjoiMjAxMy0wOC0wNlQxMjowMDowMC4wMDBaIiwiY29uZGl0aW9ucyI6W3siYnVja2V0IjoiZXhhbXBsZWJ1Y2tldCJ9LFsic3RhcnRzLXdpdGgiLCIka2V5IiwidXNlci91c2VyMS8iXSx7ImFjbCI6InB1YmxpYy1yZWFkIn0seyJzdWNjZXNzX2FjdGlvbl9yZWRpcmVjdCI6Imh0dHA6Ly9hY2w2LnMzLmFtYXpvbmF3cy5jb20vc3VjY2Vzc2Z1bF91cGxvYWQuaHRtbCJ9LFsic3RhcnRzLXdpdGgiLCIkQ29udGVudC1UeXBlIiwiaW1hZ2UvIl0seyJ4LWFtei1tZXRhLXV1aWQiOiIxNDM2NTEyMzY1MTI3NCJ9LFsic3RhcnRzLXdpdGgiLCIkeC1hbXotbWV0YS10YWciLCIiXSx7IngtYW16LWNyZWRlbnRpYWwiOiJBS0lBSU9TRk9ETk43RVhBTVBMRS8yMDEzMDgwNi91cy1lYXN0LTEvczMvYXdzNF9yZXF1ZXN0In0seyJ4LWFtei1hbGdvcml0aG0iOiJBV1M0LUhNQUMtU0hBMjU2In0seyJ4LWFtei1kYXRlIjoiMjAxMzA4MDZUMDAwMDAwWiJ9XX0=
    

    Am I doing something wrong, or is there a bug in Amazon's example?