【问题标题】:Force JSON.stringify to escape forward slash (i.e. `\/`)强制 JSON.stringify 转义正斜杠(即 `\/`)
【发布时间】:2016-03-07 10:33:44
【问题描述】:

我正在nodejs 中编写一个服务,以替换在.NET 中编写的现有系统。该服务提供一个 JSON API,其中一个调用返回一个日期。 JSON 的 Microsoft 日期格式是/是,其中 1599890827000 是毫秒偏移量:

/Date(1599890827000)/

我遇到的问题是JSON.stringify(用于res.sendexpress 中的res.json)不会转义正斜杠,但现有的Microsoft 库(System.Web.Script.Serialization.JavaScriptSerializer)希望转义正斜杠。

例如,客户端期望这样的 JSON:

{
  "Expires": "\/Date(1599890827000)\/"
}

但是JSON.stringify 会产生以下结果:

{
  "Expires": "/Date(1599890827000)/"
}

第二个结果完全有效,但 Microsoft 库不喜欢它,无法解析。

有什么办法可以强制 Express/Node/JSON 转义 JSON.stringify 中的正斜杠或处理这种情况?

我可以在运行stringify 后使用正则表达式替换,但由于我们在项目中使用的对象缓存系统,在发送到客户端之前必须转换为 JSON 而不是让其发送是非常麻烦的。

注意:我无法更改客户端,只能更改 api 服务。

【问题讨论】:

  • “但现有的 Microsoft 库 (System.Web.Script.Serialization.JavaScriptSerializer) 预计正斜杠会被转义” 以我的经验来说不是。这将是非常奇怪的,因为没有理由在 JSON 或 JavaScript 中转义它们。我怀疑您的问题出在其他地方。
  • 确实很奇怪,但没有转义的正斜杠,我得到了这个异常System.FormatException: /Date(1599898027000)/ is not a valid value for DateTime.,我无法更改客户端
  • 迟到总比没有好,但我对这种行为有一个解释。 This blog post from 2008 在这里概述了 .NET 团队的决定;基本上,他们需要一种方法来区分日期和字符串,并决定为此目的故意使用转义的正斜杠,因为“实际上我没有理由想到你为什么要这样做”。个人意见:绝对不是从雷德蒙德出来的最佳决定。但无论如何,它已经进入了野外。

标签: javascript json node.js


【解决方案1】:

Replacer happens before escaping,留给你:

"/Date(1599890827000)/"

或者:

"\\/Date(1599890827000)\\/"

实际上,您必须在结果输出上运行字符串替换:

JSON.stringify(data).replace(/\//g, '\\/');

这意味着您将无法使用 res.json(data) 内置的 express,可能需要编写一个函数来替换它,例如:

function dotNetJSONResponse(res, data) {

    var app = res.app;
    var replacer = app.get('json replacer');
    var spaces = app.get('json spaces');
    var body = JSON.stringify(data, replacer, spaces);

    if (!this.get('Content-Type')) {
        res.set('Content-Type', 'application/json');
    }

    return res.send(body.replace(/\//g, '\\/'));
}

称它为:

app.get('/url', function (req, res) {
     dotNetJSONResponse(res, data);
});

然而,也就是说,修复 .NET 中的行为将是更向前兼容的解决方案。

【讨论】:

  • 是的,这就是我的想法:(
【解决方案2】:

使用replacer参数

function replaceSlashes(key, value) 
{
  if ( typeof value == "string")
  {
    value = value.replace(/\//g, "\\/");
  }
  return value;
}

var jsonString = JSON.stringify(jsonString, replaceSlashes);

它仍然会产生一个双反斜杠,因为 stringify 方法本身不会产生一个不转义的单斜杠。\

你需要尝试这样的事情

JSON.stringify({
  "Expires": "\/Date(1599890827000)\/"
}, replaceSlashes).replace(/\\\\/g, "\\");

【讨论】:

  • @T.J.Crowder 请检查一下,它现在正在逃逸
  • 谢谢,但这会产生 \\/Date(1599890827000)\\/ 而不是 \/Date(1599890827000)\/我猜是因为 stringify 然后转义了新的反斜杠
  • @antfx 直接使用 stringify 方法是不可能的。您将需要尝试类似JSON.stringify({ "Expires": "\/Date(1599890827000)\/" }, replaceSlashes).replace(/\\\\/g, "\\") 检查更新
  • 是的,它可以工作,但正如我在原始帖子中提到的那样,由于我们使用的对象缓存系统,我理想地希望在全局或 Express 中设置一些东西
  • @antfx 我不确定我是否理解 either globally or in Express 。抱歉,如果您是这个意思,我还没有研究过 Express.js。
猜你喜欢
  • 1970-01-01
  • 2012-04-29
  • 2015-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多