JSON.stringify在属性上没有引号?


95

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

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

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

有谁知道像上面这样格式化JavaScript对象的字符串化路由?

Answers:


115

在大多数情况下,此简单的正则表达式解决方案可取消对JSON属性名称的引用:

const object = { name: 'John Smith' };
const json = JSON.stringify(object);  // {"name":"John Smith"}
console.log(json);
const unquoted = json.replace(/"([^"]+)":/g, '$1:');
console.log(unquoted);  // {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/


3
-1也不是我,但是您必须仔细阅读问题。OP需要将一个对象编码为(破碎的)json,而不是解析/评估它。
Salman A

7
@Derek这种方法不可靠。例如,输入以下内容{"foo":"e\":bar"}:(有效JSON)变为{foo:e:bar"}(...)!
罗布W

1
@Derek /\\\"/可以简化为/\\"/。不要忘记添加全局标志/\\"/g,否则它将在具有多个的字符串上中断\"。至于随机字符,切勿使用文字U + FFFF,以防编辑器窒息,而是转义序列。用于恢复的正则表达式将变为/\uFFFF/g
罗布W

2
@Derek朕会功夫您的正则表达式/\"([^(\")"]+)\":/g可以简化为/"([^"]+)":/g,请参见regex101.com/r/qnz0ld/2
tanguy_k

1
@endriu在这种情况下,只需添加一个额外的空值检查即可。
德里克·朕会功夫,

18

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

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

因此,您要找的基本上是对象检查器,而不是JSON转换器。JSON格式指定所有属性必须用双引号引起来。因此,不会有JSON转换器,做你想做的,因为这是根本就不是一个JSON format.Specs这里: https://developer.mozilla.org/en-US/docs/Using_native_JSON

根据服务器的语言,需要字符串对象还是检查对象。


1
非常感谢你!这正是我想要的。我使用json在ws服务器上向我的游戏发送数据,不管是否相信,不必处理属性名称周围的多余引号可以节省大量数据!为了澄清.toSource()起见,在nodejs中也可以正常工作,但不适用于数组中的对象。该util检查在数组这是美妙的数组和对象的作品,喜欢它。
NiCk Newman

3
util.inspect()在将对象写入Neo4j查询中时,对我来说真是太棒了,可以一次设置多个参数。
agm1984

1
通过nodejs链接:> util.inspect()方法返回用于调试的对象的字符串表示形式。util.inspect的输出可能随时更改,因此不应以编程方式依赖它。
彼得·罗伦

5

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

修改后不要包括该库。取而代之的是仅取相关(stringify)部分,或至少JSON用其他内容代替,例如。FAKEJSON

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


当您可以使用纯JavaScript进行操作时,为什么还要一个额外的库?
德里克·朕会功夫,2012年

这是一个好主意。我将分叉存储库,删除引号,然后将JSON对象重命名为FAILJSON之类的有趣东西,以表明您在使用实际的JSON对象或实际的JSON。
RichardTowers 2012年

@Derek库不应作为一个整体包含在内。只参加JSON.stringify,并删除引号。由于该库是由定义JSON的人创建的,因此我们可以确定结果是非常有效的JSON。
Rob W

看起来这是最好的方法。
德里克·朕会功夫,2012年

是的,同意德里克。尽管他的替代者工作得很好,但我对克劳福德的代码更自信,对derek哈哈毫无敬意。 .toSource()效果很好,但不包括如果您的对象位于数组中,这是一个令人毛骨悚然的问题(并且我位于节点上,因此浏览器兼容性不是问题:P),所以我也会使用此方法,感谢@RobW,jsfiddle链接似乎被卡在加载页面上:(
NiCk Newman

3

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

否则,将详细的错误报告提交给他们,其中包括一个很好的论据,说明为什么应当符合标准。除了消除源问题以外,任何其他解决方案都不是真正的解决方案。

一种快速的N肮脏的解决方法可能是在解析字符串之前将其通过正则表达式进行管道传输:

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

或者,如果您想进行更多的语法解析,则尝试调整现有的javascript JSON解析器(例如this)。




2

@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" || obj_from_json instanceof Date || obj_from_json === null){
        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(",")
            }}`;
};

1
您也应该使用JSON.stringifyinstanceof Date。'null'如果obj_from_json为null,也返回。
Far Dmitry,

1
我只是通过更改第二个if条件来修正@FarDmitry提出的问题,使其看起来像这样:if(typeof obj_from_json !== "object" || obj_from_json instanceof Date || obj_from_json === null)
Brunno Vodola Martins,

2

JSON5.stringify

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

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.