【问题标题】:Needing an alternative to eval() and better way for replacing string values需要 eval() 的替代方法和更好的方法来替换字符串值
【发布时间】:2017-10-07 05:15:05
【问题描述】:

我正在使用的 API 使用 base64 编码的 ruby​​ 哈希(类似于 json 对象,但专门针对 ruby​​)响应,该哈希在 base64 编码之前已转换为字符串

从javascript中检索编码字符串后,解码后我得到一个与它在服务器上起源的ruby字符串形状相同的字符串

// Decoded example String
"{:example=>'string',:another_example=>'string'}"

我能够使用字符串替换和 eval() 将 ruby​​ 字符串解析为 JSON 对象,但我知道 eval() 是邪恶的。此外,没有办法处理将来可能出现的任何其他键值对。

在没有 eval 和直接字符串替换的情况下应该如何重写?

var storedToken = base64url.decode(window.localStorage.authtoken).replace(':example=>', 'example:').replace(':another_example=>', 'another_example:')
var parsedTokenString = JSON.stringify(eval('(' + storedToken + ')'))
var newJsonObject = JSON.parse(parsedTokenString)

【问题讨论】:

  • @SiddharthNand 除了标题之外没有什么相似之处
  • 更改标题以防万一。
  • 如果服务器在你的控制之下,通过.to_jsonjson 包中将其转换为json 应该是一个更好的主意。
  • 这是副本,但该问题还没有答案。 stackoverflow.com/questions/35109343/…
  • 如果您更新了字符串替换以双引号引用属性名称并将值的单引号转换为双引号,我认为您将拥有有效的 JSON,然后您可以直接传递给 JSON.parse() 而无需eval()。请注意,在代码中,您已经拥有 .stringify().parse() 是多余的,因为 eval() 将已经返回所需的对象。 (顺便说一句,there is no such thing as a "JSON object"。)

标签: javascript json


【解决方案1】:

替换然后JSON.parse:

 const storedToken = "{:example=>'string',:another_example=>'string'}";
 
 const json = storedToken
   .replace(/:(\w+)/g, '"$1"')
   .replace(/=>/g, ':')
   .replace(/'/g, '"');

const obj = JSON.parse(json)

console.log(obj);

当字符串值包含 :foo 或转义单引号之类的内容时,您可能需要加强这一点以避免出现问题。

但是,正如其他答案和 cmets 中所述,您应该真正更改服务器以返回 JSON,这对于 Ruby 的 to_json 来说很容易。

【讨论】:

    【解决方案2】:

    所以你有一个像这样的字符串:

    "{:example=>'string',:another_example=>'string'}"
    

    您想转换为像(使用 JSON)这样的对象:

    '{":example":"string", ":another_example":"string"}'
    

    我不清楚:example 之前的冒号是属性名称的一部分还是表示属性名称的标记,我假设它是名称的一部分(但这很容易修改)。

    可以使用正则表达式,但是如果标记是:

    {   start of notation
    =>  property name, value separator
    ,   property/value pair separator
    }   end of notation
    

    那么一个简单的解析器/格式化器可能是这样的:

    function stringToJSON(s) {
    
      var resultText = '';
      var tokens = {
        '{' : '{',  // token: replacement 
        '=>': ':',
        ',' : ',',
        '}' : '}'
      };
      var multiTokens = {
        '=': '=>' // token start: full token
      };
      var buff = '';
    
      // Process each character
      for (var i = 0, iLen = s.length; i < iLen; i++) {
    
        // Collect characters and see if they match a token
        buff = s[i];
    
        // Deal with possible multi-character tokens
        if (buff in multiTokens) {
    
          // Check with next character and add to buff if creates a token
          // Also increment i as using next character
          if ((buff + s[i + 1]) in tokens) {
            buff += s[++i];
          }
        }
    
        // Now check in tokens
        if (buff in tokens) {
          // Tokens are always surrounded by ", except for first { and last }
          // but deal with those at the end
          resultText += '"' + tokens[buff] + '"';
    
          // Otherwise, deal with single characters
        } else {
    
          // Single quotes not allowed
          if (buff == "'") buff = '';
    
          // Add buff to result
          resultText += buff;
        }
      }
      // Remove leading and trailing "
      return resultText.replace(/^\"|\"$/g, '');
    }
    
    var s = "{:example=>'string',:another_example=>'string'}";
    
    console.log(stringToJSON(s));
    
    // Convert to object
    console.log(JSON.parse(stringToJSON(s)));

    你的字符串表示法可能更复杂,但我想你明白了它的要点。您可能需要修剪标记周围的空白,但由于属性名称没有被引号包围,因此很难知道要保留什么以及丢弃什么。您可以通过引用在数据中包含标记,然后丢弃引号字符,例如:

    \=>
    

    可以被视为文字“=>”,而不是标记。

    可以相当容易地添加更多令牌和处理步骤。多字符标记可能会变得有趣,尤其是当您选择 3 或字符时。

    数组方法和正则表达式可用于标记匹配和处理,但是我认为循环是开始对逻辑进行排序的好地方,以后可以添加糖。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-24
      • 2012-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多