【问题标题】:Convert object string to JSON将对象字符串转换为 JSON
【发布时间】:2012-02-20 15:03:16
【问题描述】:

如何使用 JavaScript(或 jQuery)将描述对象的字符串转换为 JSON 字符串?

例如:转换这个(不是一个有效的 JSON 字符串):

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"

进入这个:

str = '{ "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] }'

如果可能,我希望避免使用eval()

【问题讨论】:

  • 为什么你的字符串首先不是有效的 JSON?你是怎么产生的?
  • 字符串存储在data-attrubute 中,如下所示:<div data-object="{hello:'world'}"></div> 我不想在 HTML 中使用单引号(因此它可能不可信)
  • @snorpey: <div data-object='{"hello":"world"}'></div> 是 100% 有效的 HTML(单引号与信任与否有什么关系?)。如果你这样做,你可以JSON.parse它,它会正常工作。 注意:键也需要引用。
  • @Rocket 感谢您的努力!我只是想找到一种方法来避免在 HTML 中使用单引号(即使它是 100% 有效)和 JSON 表示法。
  • @snorpey:他们的方法是首先不将 JSON 放在 HTML 属性中。我猜你可以使用双引号,并转义 JSON <div data-object="{\"hello\":\"world\"}"></div> 中的双引号。如果您不想在属性中使用有效的 JSON,那么您将不得不制作自己的格式并自己解析。

标签: javascript json object


【解决方案1】:

这也可以

let str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"
let json = JSON.stringify(eval("("+ str +")"));

【讨论】:

    【解决方案2】:

    我希望这个小函数可以将无效的 JSON 字符串转换为有效的字符串。

    function JSONize(str) {
      return str
        // wrap keys without quote with valid double quote
        .replace(/([\$\w]+)\s*:/g, function(_, $1){return '"'+$1+'":'})    
        // replacing single quote wrapped ones to double quote 
        .replace(/'([^']+)'/g, function(_, $1){return '"'+$1+'"'})         
    }
    

    结果

    let invalidJSON = "{ hello: 'world',foo:1,  bar  : '2', foo1: 1, _bar : 2, $2: 3, 'xxx': 5, \"fuz\": 4, places: ['Africa', 'America', 'Asia', 'Australia'] }"
    JSON.parse(invalidJSON) 
    //Result: Uncaught SyntaxError: Unexpected token h VM1058:2
    JSON.parse(JSONize(invalidJSON)) 
    //Result: Object {hello: "world", foo: 1, bar: "2", foo1: 1, _bar: 2…}
    

    【讨论】:

    • 我们正在尝试使用 JSON.parse 我们的代码对 b 进行反评估,这看起来是一个不错的解决方案。我们仍然需要手动处理不断的替换,但至少这允许包含这些情况。
    • 几乎完美。当: 处于其中一个值时不起作用。
    • eval 是纯粹的邪恶,我认为这是要走的路
    • 绝对的天才
    【解决方案3】:

    使用 new Function() 优于 eval,但仍应仅用于安全输入。

    const parseJSON = obj => Function('"use strict";return (' + obj + ')')();
    
    console.log(parseJSON("{a:(4-1), b:function(){}, c:new Date()}"))
    // outputs: Object { a: 3, b: b(), c: Date 2019-06-05T09:55:11.777Z }
    

    来源: MDN, 2ality

    【讨论】:

      【解决方案4】:
      var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
      var json = JSON.stringify(eval("(" + str + ")"));
      

      【讨论】:

        【解决方案5】:

        您最好和最安全的选择是JSON5 – JSON for Humans。它是专门为该用例创建的。

        const result = JSON5.parse("{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }");
        
        console.log(JSON.stringify(result));
        <script src="https://cdnjs.cloudflare.com/ajax/libs/json5/0.5.1/json5.min.js"></script>

        【讨论】:

          【解决方案6】:

          您需要使用“eval”然后 JSON.stringify 然后 JSON.parse 到结果。

           var errorString= "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
           var jsonValidString = JSON.stringify(eval("(" + errorString+ ")"));
           var JSONObj=JSON.parse(jsonValidString);
          

          【讨论】:

            【解决方案7】:

            也许你必须试试这个:

            str = jQuery.parseJSON(str)
            

            【讨论】:

            • 问题指定为“或 jQuery”,如果你有它,这是完美的解决方案。
            【解决方案8】:

            使用一个正则表达式而不使用 eval 的解决方案:

            str.replace(/([\s\S]*?)(')(.+?)(')([\s\S]*?)/g, "$1\"$3\"$5")
            

            我相信这应该适用于多行和所有可能出现的单引号“字符串”(/g 标志)替换为双引号“字符串”。

            【讨论】:

              【解决方案9】:

              var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }" var fStr = str .replace(/([A-z]*)(:)/g, '"$1":') .replace(/'/g, "\"")

              console.log(JSON.parse(fStr))

              对不起,我在用手机,这是一张照片。

              【讨论】:

                【解决方案10】:

                只是为了它的怪癖,你可以通过babel-standalone转换你的字符串

                var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
                
                function toJSON() {
                  return {
                    visitor: {
                      Identifier(path) {
                        path.node.name = '"' + path.node.name + '"'
                      },
                      StringLiteral(path) {
                        delete path.node.extra
                      }
                    }
                  }
                }
                Babel.registerPlugin('toJSON', toJSON);
                var parsed = Babel.transform('(' + str + ')', {
                  plugins: ['toJSON']
                });
                var json = parsed.code.slice(1, -2)
                console.log(JSON.parse(json))
                <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

                【讨论】:

                  【解决方案11】:

                  对于上面的简单示例,您可以使用 2 个简单的正则表达式替换来做到这一点:

                  var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
                  str.replace(/(\w+):/g, '"$1":').replace(/'/g, '"');
                   => '{ "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] }'
                  

                  大警告:这种天真的方法假定对象没有包含': 字符的字符串。例如,我想不出不使用eval 将以下对象字符串转换为 JSON 的好方法:

                  "{ hello: 'world', places: [\"America: The Progressive's Nightmare\"] }"
                  

                  【讨论】:

                    【解决方案12】:

                    使用下面链接中的简单代码:

                    http://msdn.microsoft.com/es-es/library/ie/cc836466%28v=vs.94%29.aspx

                    var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
                    var contact = JSON.parse(jsontext);
                    

                    倒转

                    var str = JSON.stringify(arr);
                    

                    【讨论】:

                    • 为了类型安全,通过 new String(jsontext) 将 jsontext 转换为 String 对象可能会更好。
                    • @fuzzyanalysis:不,不应该使用原始包装器。
                    • JSON.parse() 应该是@LouiseMcMahon 所述的可接受的答案
                    【解决方案13】:

                    有一个更简单的方法来完成这个壮举,只需劫持一个虚拟元素的 onclick 属性以强制将您的字符串作为 JavaScript 对象返回:

                    var jsonify = (function(div){
                      return function(json){
                        div.setAttribute('onclick', 'this.__json__ = ' + json);
                        div.click();
                        return div.__json__;
                      }
                    })(document.createElement('div'));
                    
                    // Let's say you had a string like '{ one: 1 }' (malformed, a key without quotes)
                    // jsonify('{ one: 1 }') will output a good ol' JS object ;)
                    

                    这是一个演示: http://codepen.io/csuwldcat/pen/dfzsu(打开你的控制台)

                    【讨论】:

                      【解决方案14】:

                      我把我的答案献给对这个旧线程感兴趣的人。

                      我为 jQuery 插件创建了 HTML5 data-* parserdemo,它们在不使用 eval() 的情况下将格式错误的 JSON 字符串转换为 JavaScript 对象。

                      它可以传递HTML5 data-* 属性如下:

                      <div data-object='{"hello":"world"}'></div>
                      <div data-object="{hello:'world'}"></div>
                      <div data-object="hello:world"></div>
                      

                      进入对象:

                      {
                          hello: "world"
                      }
                      

                      【讨论】:

                        【解决方案15】:

                        谨慎使用(因为eval()):

                        function strToJson(str) {
                          eval("var x = " + str + ";");
                          return JSON.stringify(x);
                        }
                        

                        调用为:

                        var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
                        alert( strToJson(str) );
                        

                        【讨论】:

                        • 致匿名的反对者。我挑战你提供更好的解决方案。除此之外,否决票的理由会很好。
                        • @Rocket:你错了。 a)eval() 是唯一的方法。 b)我警告过OP。 c) 查看 Matthew Crumley 的回答并想出一个更好的解释。 (哦,还有 d)声明 eval() is bad 在这种广义形式中是无稽之谈。)
                        • @Rocket:啊,误会了。抱歉,我以为反对票是你的。 :)
                        • @kuboslav:它工作正常,你测试过吗?他正在做eval("var x = " + str + ";"),这是完全有效的 JS。你不需要做var x = ({a:12})
                        • @kuboslav 它在 IE7 中不起作用,因为 IE7 没有原生 JSON 支持。只要您使用json2.js,它就会开始工作。不要那么高兴。
                        【解决方案16】:

                        如果字符串来自受信任的来源,您可以使用eval 然后JSON.stringify 结果。像这样:

                        var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
                        var json = JSON.stringify(eval("(" + str + ")"));
                        

                        请注意,当您eval 一个对象字面量时,它必须用括号括起来,否则大括号将被解析为块而不是对象。

                        我也同意 cmets 提出的问题,即最好只用有效的 JSON 编码对象,然后避免解析、编码,然后大概再解析它再次。 HTML 支持单引号属性(只需确保对字符串中的任何单引号进行 HTML 编码)。

                        【讨论】:

                        • 这没有意义,如果字符串来自受信任的来源,为什么我们将其转换为有效的 json。
                        • @allenhwkim 想法是将无效的 JSON 转换为有效的 JSON,因此 eval 将字符串转换为 JavaScript 对象(只要字符串表示有效的 JavaScript,即使它不是有效的 JSON)。然后JSON.stringify 从一个对象转换回一个(有效的)JSON 字符串。如果字符串不是来自受信任的来源,则调用 eval 是危险的,因为它实际上可以运行任何 JavaScript,这会打开跨站点脚本攻击的可能性。
                        • 在这种情况下,如果构造字符串,eval 仍然会做坏事,例如,像这样: var str = "(function() {console.log(\"bad\")}) ()";
                        • 使用 eval() 将执行 JS 代码。它很容易被滥用。
                        • @allenhwkim:我们从不信任任何来源。对 IT 的信任意味着检查、检查和再检查。
                        【解决方案17】:

                        您的字符串不是有效的 JSON,因此 JSON.parse(或 jQuery 的 $.parseJSON)将不起作用。

                        一种方法是使用eval“解析”“无效”JSON,然后使用stringify将其“转换”为有效JSON。

                        var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"
                        str = JSON.stringify(eval('('+str+')'));
                        

                        我建议不要尝试“修复”无效的 JSON,而是首先从有效的 JSON 开始。 str 是如何生成的,应该在生成之前修复,而不是生成之后。

                        编辑:您说(在 cmets 中)此字符串存储在数据属性中:

                        <div data-object="{hello:'world'}"></div>
                        

                        我建议你在这里修复它,所以它可以是JSON.parsed。首先,它们的键和值都需要用双引号引起来。它应该看起来像(HTML 中的单引号属性有效):

                        <div data-object='{"hello":"world"}'></div>
                        

                        现在,您可以使用 JSON.parse(或 jQuery 的 $.parseJSON)。

                        var str = '{"hello":"world"}';
                        var obj = JSON.parse(str);
                        

                        【讨论】:

                          【解决方案18】:

                          您必须编写圆括号,因为没有它们eval 会将大括号内的代码视为命令块。

                          var i = eval("({ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] })");
                          

                          【讨论】:

                            【解决方案19】:

                            免责声明:不要在家里尝试这个,或者任何需要其他开发者认真对待的事情:

                            JSON.stringify(eval('(' + str + ')'));
                            

                            在那里,我做到了。
                            尽量不要这样做, eval 对你不利。如上所述,为旧版浏览器(IE7 及以下)使用 Crockford 的 JSON shim

                            此方法要求您的字符串是有效的javascript,它将被转换为一个 javascript 对象,然后可以序列化为 JSON。

                            编辑: 按照 Rocket 的建议修复。

                            【讨论】:

                            • 应该是JSON.stringify(eval('('+str+')'));,不是我宽恕eval,而是他的字符串不是有效的JSON,所以JSON.parse不起作用。
                            【解决方案20】:

                            jQuery.parseJSON

                            str = jQuery.parseJSON(str)
                            

                            编辑。前提是您有一个有效的 JSON 字符串

                            【讨论】:

                            • true 我看到的问题是如何将 JSON 字符串转换为对象
                            【解决方案21】:

                            Douglas Crockford 有一个转换器,但我不确定它是否有助于将坏 JSON 转换为好 JSON。

                            https://github.com/douglascrockford/JSON-js

                            【讨论】:

                            • 这并没有真正的帮助,因为字符串不是有效的 JSON。
                            猜你喜欢
                            • 2019-08-27
                            • 2020-05-27
                            • 1970-01-01
                            • 1970-01-01
                            • 2011-04-23
                            • 2012-06-14
                            • 2015-01-03
                            • 1970-01-01
                            相关资源
                            最近更新 更多