如何正确解码来自 API 返回的 base64 编码字符串

huangapple go评论61阅读模式
英文:

How to decode a base64 encoded string returned from an api correctly

问题

const decodedObject: {
  foo?: string;
} = JSON.parse(
  Buffer.from(encodedString.replace("b'", '').replace("'", ''), 'base64').toString(),
);
英文:

Having a base64 string encoded JSON like object coming from a python API, what is the correct way to decode and parse the encoded JSON in javascript?

Python makes it a byte string literal by adding b prefix and additional apostrophes.

I have written the following function using Buffer.from and buf.toString methods, which is working fine, but the problem is, the string I receive from the API has b'<encoded-string>' format. With the initial b and the apostrophes(').

const decodedObject: {
  foo?: string;
} = JSON.parse(
  Buffer.from(encodedString.replace("b'", '').replace("'", ''), 'base64').toString(),
);

atob and btoa seems deprecated I as understand from the warning in my IDE. That's why I used Buffer methods

So, my question is: Removing those apostrophes and b manually didn't feel right. Is there something I might be missing?

For example creating the encoded base64 in python:

>>> import base64
>>> "https://example.com?encoded={}".format(base64.b64encode(str({"foo":"bar"}).encode('utf-8')))
"https://example.com?encoded=b'eydmb28nOiAnYmFyJ30='"

In order to decode that base64 in javascript, I need to first remove those prefix and apostrophes.

> console.log(atob('eydmb28nOiAnYmFyJ30='))
{'foo': 'bar'}

答案1

得分: 2

这里的问题是,你的Python代码在假装字符串是JSON,而实际上没有使用json库生成正确的JSON。

所以,让我们来修复这个问题:

import base64
import json

data = { "foo": "bar" }
encoded_value = base64.b64encode(json.dumps(data))
url = f"https://example.com?encoded={encoded_value}"

至此,encoded URL查询参数现在是JS端上的一个普通、轻松解码的值,因为我们可以保证它是正确的JSON,只是经过了base64编码。

这意味着为了在JS端解析它,我们只需按照以下明显的步骤进行操作:

  1. 获取查询值,
  2. 解码它,
  3. 将其解析为JSON

因此:

// 我不知道你是在运行Node、浏览器、Deno等。
// 所以替换为window.location或你的框架的路径对象。
const url = new URL(request.path)

// 获取编码值
const query = new URLSearchParams(url.search)
const encoded = query.get(`encoded`)

// 将其转换回JSON字符串并解析
const decoded = base64Decode(encoded); // 再次强调,不知道你在哪里运行这个代码。
try {
  const unpacked = JSON.parse(decoded);
  console.log(unpacked); // { foo: "bar" }
} catch (e) {
  // 一定要在try/catch中运行JSON.parse,因为它可能会抛出异常。
}

需要注意的是,base64Decode(encoded) 是一个占位符,代表你使用的任何base64库。

英文:

The problem here is that your Python code is pretending strings are JSON, instead of actually using the json library to generate proper JSON.

So, let's fix that:

import base64
import json

data = { "foo": "bar" }
encoded_value = base64.b64encode(json.dumps(data))
url = f"https://example.com?encoded={encoded_value}"

And done, the encoded URL query argument is now a normal, trivially decoded value on the JS side, because we're guaranteed that it's proper JSON, just base64 encoded.

Which means that in order to unpack that on the JS side, we just run through the obvious steps:

  1. get the query value,
  2. decode it,
  3. parse it as JSON

So:

// I have no idea if you're running Node, a browser, Deno, etc.
// so substitute window.location or your framework's path object.
const url = new URL(request.path)

// get the encoded value
const query = new URLSearchParams(url.search)
const encoded = query.get(`encoded`)

// turn it back into a JSON string and parse that
const decoded = base64Decode(encoded); // again, no idea where you're running this.
try {
  const unpacked = JSON.parse(decoded);
  console.log(unpacked); // { foo: "bar" }
} catch (e) {
  // ALWAYS run JSON.parse in a try/catch because it can, and will, throw.
}

Noting that that base64Decode(encoded) is a stand-in for whatever base64 library you're using.

huangapple
  • 本文由 发表于 2023年2月16日 02:26:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75464013.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定