JSON.stringify属性没有引号?

jad*_*ent 74 javascript json

我正在使用一个使用不正确的JSON格式的服务(属性周围没有双引号).所以我需要发送

{ name: "John Smith" } 代替 { "name": "John Smith" }

此格式无法更改,因为这不是我的服务.

有人知道如上所述格式化JavaScript对象的字符串化路由吗?

Der*_*會功夫 95

var json = '{ "name": "John Smith" }';       //Let's say you got this
json = json.replace(/\"([^(\")"]+)\":/g,"$1:");  //This will remove all the quotes
json;                                        //'{ name: "John Smith" }'
Run Code Online (Sandbox Code Playgroud)

正则表达式将删除所有引号,最重要的是,它不需要库!

极端情况:

var json = '{ "name": "J\\":ohn Smith" }'
json.replace(/\\"/g,"\uFFFF"); //U+ FFFF
json = json.replace(/\"([^"]+)\":/g,"$1:").replace(/\uFFFF/g,"\\\"");
//'{ name: "J\":ohn Smith" }'
Run Code Online (Sandbox Code Playgroud)

特别感谢Rob W修复它.


更新:

在正常情况下,上述正则表达式将起作用,但在数学上,不可能用正则表达式来描述JSON格式,这样它就可以在每一种情况下工作(使用正则表达式计算相同数量的大括号是不可能的.)因此,我有通过通过本机函数正式解析JSON字符串并重新序列化来创建一个新函数来删除引号:

function stringify(obj_from_json){
    if(typeof obj_from_json !== "object" || Array.isArray(obj_from_json)){
        // not an object, stringify using native function
        return JSON.stringify(obj_from_json);
    }
    // Implements recursive object serialization according to JSON spec
    // but without quotes around the keys.
    let props = Object
        .keys(obj_from_json)
        .map(key => `${key}:${stringify(obj_from_json[key])}`)
        .join(",");
    return `{${props}}`;
}
Run Code Online (Sandbox Code Playgroud)

示例:https://jsfiddle.net/DerekL/mssybp3k/

请注意,代码是用ES6编写的,可能需要对旧版浏览器进行转换或手动翻译.

  • @Derek这种方法**不可靠**.例如,取这个输入:`{"foo":"e \":bar"}`(有效的JSON)变为`{foo:e:bar"}`(...)! (4认同)
  • -1也不是我,但你必须仔细阅读这个问题.OP需要将对象编码为(损坏的)json,而不是解析/评估它. (3认同)
  • @Derek我会功夫你的正则表达式`/\"([^(\")"]+)\":/g`可以简化为`/"([^"]+)":/g`,见https ://regex101.com/r/qnz0ld/2 (2认同)

fin*_*ino 14

看起来这是一个您正在寻找的简单的Object toString方法.

在Node.js中,这是通过使用util对象并调用util.inspect(yourObject)来解决的.这将为您提供所需的一切.请点击此链接获取更多选项,包括方法应用的深度.http://nodejs.org/api/util.html#util_util_inspect_object_options

所以,你要找的基本上是一个对象检查器而不是JSON转换器.JSON格式指定必须用双引号括起所有属性.因此,没有JSON转换器可以执行您想要的操作,因为它不是JSON格式.此处的规格如下:https: //developer.mozilla.org/en-US/docs/Using_native_JSON

根据服务器的语言,您需要对象进行字符串或检查.

  • 在将对象写入Neo4j查询中时,`util.inspect()`对我来说真是太棒了,可以一次设置多个参数。 (2认同)
  • 来自nodejs 链接: > util.inspect() 方法返回用于调试的对象的字符串表示形式。util.inspect 的输出可能随时更改,不应以编程方式依赖。 (2认同)
  • 好的,那么如何在客户端 JavaScript 中执行此操作呢?你能举个例子吗?如果没有它,这并不能真正回答问题。 (2认同)

vas*_*vas 10

使用JSON5.stringify

JSON5是 JSON 的超集,允许使用 ES5 语法,包括不带引号的属性键。JSON5 参考实现(json5npm package)提供了一个JSON5对象,该对象具有与内置JSON对象相同的方法、相同的参数和语义。

您正在使用的服务很可能正在使用此库。事实上,许多知名项目都使用 JSON5:

JSON5 于 2012 年启动,截至 2022 年,每周下载量超过 6500 万次,在 npm 上最依赖的软件包中排名前 0.1%,并已被 Chromium、Next.js、Babel 等主要项目采用、Retool、WebStorm 等等。MacOS 和 iOS 等 Apple 平台也原生支持它。

~ json5.org主页


ruf*_*fin 10

TL; DR -- 代码

关于浏览器中的后视支持,请注意以下几点:

function cleanIt(obj) {
    var cleaned = JSON.stringify(obj, null, 2);

    return cleaned.replace(/^[\t ]*"[^:\n\r]+(?<!\\)":/gm, function (match) {
        return match.replace(/"/g, "");
    });
}
Run Code Online (Sandbox Code Playgroud)

注意:截至 2021 年 6 月 18 日,IE 或任何版本的 Safari都不支持 Lookbehinds 。要在那里使用,请(?<!\\)从正则表达式中删除并注意下面提到的“陷阱”条件。

用漂亮的字符串化,使用我们的正则表达式来查找键,然后每个键匹配都通过替换函数替换,该函数说“这是您的匹配项,删除了所有双引号”。由于我们只将键匹配到它们的冒号,这正是我们想要的。

详细说明如下。


为什么接受的答案不好

不幸的是,正如Adel 指出的那样Derek 的无正则表达式解决方案存在一个非常严重的问题。它不处理对象数组。你看到它如何短路并说,“如果它是一个数组,让我们JSON.stringify处理它”?这适用于简单的值类型,但不适用于对象。

//                                        \/\/\/ OH NOES!!! \/\/\/
if (typeof obj_from_json !== "object" || Array.isArray(obj_from_json)){
    // not an object, stringify using native function
    
    return JSON.stringify(obj_from_json);
//         ^^^^^^^^^^^^^^ No! Don't do that! 
}
Run Code Online (Sandbox Code Playgroud)

用失败案例编辑了他的小提琴。这是有效载荷:

var obj = {
  name: "John Smith",
  favoriteObjects: [
    { b: "there's", c: "always", d: "something" },
    [1, 2, "spam", { f: "hello" }],
    { vowels: "are missing" },
  ],
  favoriteFruits: ["Apple", "Banana"],
};
Run Code Online (Sandbox Code Playgroud)

这是空白输出:

{
  name:"John Smith",
  favoriteObjects:[
    {
      "b":"there's",    <<< Major
      "c":"always",     <<< fails
      "d":"something"   <<< here
    },
    [
      1,2,"spam",
      {
        "f":"hello"     <<< and here.
      }
    ],
    {
      "vowels":"are missing" <<< again.
    }
  ],
  favoriteFruits:["Apple","Banana"] <<< that worked!
}
Run Code Online (Sandbox Code Playgroud)

看?尽管字符串数组 ( favoriteFruits) 有效,但我们仍然在数组中的对象(如favoriteObjects)的第二级序列化中获得了引号。坏的。


一个简单的解决方案

我花了太多时间试图清理该函数,然后才想出一个巧妙的技巧来显着降低问题的复杂性,我认为这将正则表达式带回了混合中。

让我们stringify用空格

McGuire 先生脉络中,我只想对您说一句话,一句话:

空白。

让我们JSON.stringify留一些空白。这使得正则表达式可以更容易地从键中删除引号。

用这个开始你的解决方案:

var cleaned = JSON.stringify(x, null, 2);
Run Code Online (Sandbox Code Playgroud)

调用stringify说“字符串化x(第一个参数),没有花哨的替换函数(由 的第二个参数表示null2,对于序列化中的每个深度级别,都有两个(第三个参数)空格的空格。” 这2也让我们为每个房产购买了单独的产品线。

{
  "name": "John Smith",
  "favoriteObjects": [
    {
      "b": "there's",
      "c": "always",
// etc...
Run Code Online (Sandbox Code Playgroud)

每个键现在都很好地位于一行的开头。我们可以处理。


现在清除键上的引号

让我们创建一个查找键的正则表达式,并且只查找键,然后将其周围的". 因为我们知道,钥匙都对自己行了,事情简单。

唯一真正的问题是属性的值是否包含":中途。那会把事情搞砸。

"a": [
    "This could \": be bad",
    "QQ"
]
Run Code Online (Sandbox Code Playgroud)

回顾警告

我想通过对旧浏览器花哨的负面前瞻来解决这个问题,但放弃并使用了负面的后视。Negative lookbehind 仅在 2018 年之后被部分浏览器支持这里是 2ality 的lookbehind 提案历史描述,浏览器兼容性可以在这里找到)。


正则表达式解释:

/^[\t ]*"[^:\n\r]+(?<!\\)":/gm
Run Code Online (Sandbox Code Playgroud)

那个正则...

  • 是正则表达式
    • 以。。开始 /
  • 查找以(0 到无穷大空格或制表符)开头的任何行
    • ^[\t ]*
  • 然后一个 "
    • "
  • 随后的一个或多个字符什么IS NOT一个:或一个换行符
    • [^:\n\r]+
  • 然后以两个字符结尾":否定后向警告前面没有反斜杠
  • 是否全局和多行(逐行)
    • /gm

合理成功的小提琴

结果:

{
  name: "John Smith",
  favoriteObjects: [
    {
      b: "there's",
      c: "always",
      d: "something"
    },
    [
      1,
      2,
      "spam",
      {
        f: "hello"
      }
    ],
    {
      vowels: "are missing"
    }
  ],
  favoriteFruits: [
    "Apple",
    "Banana"
  ]
}
Run Code Online (Sandbox Code Playgroud)

在贾登特提出要求后的短短八年半时间里,QED。现在就是服务!


快速更新:一个更好的答案,如果你不一定需要在代码中发生这种情况(尽管在某些用例中,你也可以直接调用这个库),可以使用prettier,它可以很好地清理事物。


Rob*_*b W 5

您可以查看由定义JSON格式的解析器创建的解析器的源代码.寻找函数调用:这些函数用引号括起来.键在326338处引用.json2.js quote

修改后不要包含库.而只是采取相关(stringify)部分,或至少替换JSON其他东西,例如.FAKEJSON.

例如,一个FAKEJSON只定义的对象stringify:http://jsfiddle.net/PYudw/


Ber*_*rgi 5

尝试将服务与 JSONP 一起使用,我猜他们在使用这种格式时提供了它。

否则,向他们提交一份详细的错误报告,包括良好的论证为什么应该符合标准。除了消除源头问题之外,任何其他解决方案都不是真正的解决方案。

一个快速而肮脏的修复可能是在解析字符串之前通过正则表达式通过管道传输字符串:

var obj = JSON.parse(str.replace(/(\{|,)\s*(.+?)\s*:/g, '$1 "$2":'));
Run Code Online (Sandbox Code Playgroud)

或者,如果您想要更具语法性的解析,您可以尝试调整现有的 javascript JSON 解析器(如这个)。


use*_*276 5

找到了一个很好的 NPM 包来做到这一点:

https://www.npmjs.com/package/stringify-object

const stringify = require('stringify-object')

let prettyOutput = stringify(json);
Run Code Online (Sandbox Code Playgroud)

工作得很好。

  • 该库不是递归的。 (2认同)