JSON.parse() 保持字符串编码

5
//string with correct json format

{"reaction":"\ud83d\udc4d","user":{"id":"xyz"}}

//after JSON.parse()

{ reaction: '', user: [Object] }

我想做的是保持反应值编码,但是JSON.parse()并不完全满足我的要求。
更新
最终,我决定保留JSON.parse(),并像@Brad建议的那样修复数据库问题。我改变了数据库格式,但这还不足以解决问题,所以我找到了这个。每个语句现在都必须以SET NAMES utf8mb4;开头,然后是查询。此外,在连接中,您必须有这些{charset : 'utf8mb4', multipleStatements: true}。没有node-mysql适当的文档,很难找到最好的答案,但最终我学到了很多东西,谢谢。

1
啊,那就是你的意思。 - Patrick Roberts
2
JSON.parse 不会对任何内容进行编码,我觉得这可能是控制台或者你记录数据的方式。解析后的数据的预期用途是什么? - James
那么当您解析数据时,可能会以某种方式对其进行操作,然后再次使用JSON.stringify进行存储在数据库中?除非您希望对象上的toString反序列化(它不会这样做),否则我无法看到这是如何发生的。 - James
1
@Adminy,你用什么查看数据库?为什么不想让它显示成一堆问号?最好将实际字符按原样存储,即使你用来查看数据库的工具不知道如何显示它们。 - Paul
1
@Adminy 请修复您的字符编码。您正在完全错误的方式解决此问题。请不要动 JSON。 - Brad
显示剩余7条评论
1个回答

2
如果您不想解码该字符串,则可以转义反斜杠,例如:"\\ud83d\\udc4d" 您控制数据来自何处吗?也许您想在 JSON.stringify 中提供一个“替换器”以转义它们,或者在 JSON.parse 中提供一个“reviver”。
对于控制 stringify 或 parse,您有哪些选项?
应用一个 reviver(已划掉)。
const myReviver = (key, val) => key === "reaction" ? val.replace(/\\/g, "\\\\") : val;

var safeObj = JSON.parse(myJson, myReviver);

注意:这似乎在浏览器中不起作用,因为\xxxx字符在reviver能够操作之前被解码在字符串中,因此没有剩余的反斜杠可供转义!

多重转义

继与OP的交谈后,发现对具有utf字符的属性添加多个转义的反斜杠最终导致所需值存储在数据库中。需要执行一些步骤才能取消转义反斜杠,直到实际的utf字符最终被暴露出来。

这很脆弱,远非明智之举,但确实有助于确定是什么导致了问题。

无反斜杠

这似乎是最佳解决方案。在将数据转换为utf字符或以任何方式处理之前,请从数据中删除所有反斜杠。基本上,在数据库中存储已禁用的“uxxxxuxxxx”代码。

这些代码可以通过使用正则表达式重新插入反斜杠在渲染点处复活为utf字符:

database_field.replace(/(u[0-9a-fA-F]{4})/g, "\\$1");

具有讽刺意味的是,这似乎跳过了UTF解释,实际上你最终得到的是一开始想要的字符串。因此,为了强制它提供以前看到的字符,可以使用以下处理方法:

emoji = JSON.parse(`{"utf": "${myUtfString}"}`).utf;

回答你的问题,我可以控制要解析的字符串,但我必须操作该字符串,不能改变其格式。 - Got To Figure
我本来想说我用了 data.replace(/\\/g, "\\\\"),它起作用了,但还是谢谢你的解决方案! - Got To Figure
复活者(reviver)显然只对键(key)等于“reaction”的解析项目应用转义。它可能会发现一些误报(我认为不可能扩大范围以进一步缩小),但比将替换应用于整个JSON字符串更安全,因为在解析期间可能会转义您需要保留未转义的某些字符。 - Raith
1
可悲的是,我开始认为复苏者并不是解决方案。在复活者能够操纵它之前,字符似乎已经在字符串中进行了转换。因此,将其应用于字符串可能是唯一的方法。如果是这样,那么值得使用更强大的正则表达式只转义该属性。 - Raith
让我们在聊天中继续这个讨论 - Got To Figure
显示剩余2条评论

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