JSON.stringify属性没有引号?

时间:2012-06-27 19:21:37

标签: javascript json

我使用的服务使用了错误的JSON格式(属性周围没有双引号)。所以我需要发送

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

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

任何人都知道使用stringify路由来格式化上面的JavaScript对象吗?

11 个答案:

答案 0 :(得分:77)

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" }'

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

极端情况:

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

特别感谢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}}`;
}

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

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

答案 1 :(得分:10)

看起来这是一个您正在寻找的简单的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

根据服务器的语言,您需要使用字符串或检查对象。

答案 2 :(得分:8)

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, "");
    });
}
<块引用>

注意: IE 不支持 Lookbehinds,奇怪的是,any version of Safari as of 18 June 2021 不支持。要在那里使用,请从正则表达式中删除 (?<!\\) 并注意下面提到的“陷阱”条件。

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

详细说明如下。


为什么接受的答案不好

不幸的是,正如Adel points out 指出的那样,Derek's regular expression-less solution 存在一个非常严重的问题。 它不处理对象数组。你看到它如何短路并说,“如果它是一个数组,让 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! 
}

我编辑了他的 fiddle with a fail case。这是有效载荷:

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

这是空白输出:

{
  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!
}

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


一个简单的解决方案

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

让我们用空格 stringify

vein of Mr. McGuire中,我只想对你说一个字,一个字:

空格。

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

从此开始您的解决方案:

var cleaned = JSON.stringify(x, null, 2);

stringify 的调用表示“stringify x(第一个参数),没有花哨的替换函数(由 null 的第二个参数表示)和两个({{的第三个参数) 1}}) 序列化中每个深度级别的空白空间。” 2 还为我们购买了每个属性的单独行。

2

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


现在清除键上的引号

让我们创建一个查找键的正则表达式,并且只查找键,并拉出它们周围的 { "name": "John Smith", "favoriteObjects": [ { "b": "there's", "c": "always", // etc... 。由于我们知道现在键都在自己的行上,所以事情要简单得多。

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

":

回顾警告

我想用 fancy negative look-ahead for older browsers 解决这个问题,但放弃并使用了否定的后视。 Negative lookbehind 仅在 2018 年之后被部分浏览器支持history of lookbehind proposal at 2ality here 的描述,浏览器兼容性可以是 found here)。


正则表达式解释:

"a": [
    "This could \": be bad",
    "QQ"
]

那个正则表达式...

  • 是正则表达式
    • /^[\t ]*"[^:\n\r]+(?<!\\)":/gm 开头
  • 查找以(0 到无穷大空格或制表符)开头的任何行
    • /
  • 然后是 ^[\t ]*
    • "
  • 然后一个或多个任何字符ISN'T"或换行符
    • :
  • 然后以两个字符 [^:\n\r]+ 结尾,即(否定后视警告前面没有反斜杠
  • 全局和多行(逐行)执行此操作
    • (?<!\\)":

Fiddle of reasonable success

结果:

/gm

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


快速更新:一个更好的答案,如果您不一定需要在代码中发生这种情况(尽管在某些用例中,您也可以直接调用此库),可以使用prettier,干净利落。

答案 3 :(得分:5)

您可以查看json2.js 的源代码,该解析器是由定义JSON格式的解析器创建的。查找quote函数调用:这些函数用引号括起一个值。密钥引用行326338

修改后不要包含库。相反,只需要使用相关的(stringify)部分,或者至少用其他内容替换JSON,例如。 FAKEJSON

例如,对象FAKEJSON仅定义了stringifyhttp://jsfiddle.net/PYudw/

答案 4 :(得分:4)

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

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

const stringify = require('stringify-object')

let prettyOutput = stringify(json);

效果很好。

答案 5 :(得分:3)

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

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

快速修复可能是在解析它之前通过正则表达式管道字符串:

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

如果您想要更多的语法分析,或者您尝试调整现有的javascript JSON解析器(如this one)。

答案 6 :(得分:2)

使用JSON5.stringify

JSON5是JSON的超集,它支持ES5语法,包括未加引号的属性键。 JSON5参考实现(json5 npm package)提供了一个JSON5对象,该对象具有与内置JSON对象相同的方法,并且具有相同的参数和语义。

您使用的服务很有可能正在使用此库。

答案 7 :(得分:1)

您的继承语法应该很容易被YAML吃掉,YAML是JSON的超集。

尝试使用JavaScript YAML解析器和转储程序:http://nodeca.github.com/js-yaml/

答案 8 :(得分:0)

CSVJSON's JSON Beautifier可以选择删除键上的引号。如果您只想要代码,可以从GitHub仓库中复制它。我modified Douglas Crockford's JSON2为此添加了支持。

答案 9 :(得分:0)

var jsonString = JSON.stringify(YOUROBJECT);

var jsonObject = JSON.parse(jsonString);

答案 10 :(得分:0)

@Derek朕会功夫感谢分享此方法,我想分享支持对字符串数组进行字符串化的代码。

export const stringifyObjectWithNoQuotesOnKeys = (obj_from_json) => {
    // In case of an array we'll stringify all objects.
    if (Array.isArray(obj_from_json)) {
        return `[${
                    obj_from_json
                        .map(obj => `${stringifyObjectWithNoQuotesOnKeys(obj)}`)
                        .join(",")
                }]` ;
    }
    // not an object, stringify using native function
    if(typeof obj_from_json !== "object"){
        return JSON.stringify(obj_from_json);
    }
    // Implements recursive object serialization according to JSON spec
    // but without quotes around the keys.
    return `{${
            Object
                .keys(obj_from_json)
                .map(key => `${key}:${stringifyObjectWithNoQuotesOnKeys(obj_from_json[key])}`)
                .join(",")
            }}`;
};