需要替代eval()和替换字符串值的更好方法

时间:2017-05-09 03:28:39

标签: javascript json

我正在使用的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)

2 个答案:

答案 0 :(得分: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或转义单引号等内容时,您可能希望收紧这一点以避免事情中断。

但是,正如其他答案和评论中所提到的,你应该真正改变服务器以返回JSON,这对Ruby的to_json来说很容易。

答案 1 :(得分:0)

所以你有一个像:

这样的字符串
"{: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)));
&#13;
&#13;
&#13;

你的字符串符号可能更复杂,但我认为你得到了它的要点。您可能需要修剪令牌周围的空白,但由于属性名称不被引号括起来,因此很难知道要保留什么以及要扔掉什么。您可以通过引用,然后丢弃引号字符来包含数据中的标记,例如:

\=>

可以视为文字&#34; =&gt;&#34;,而不是代币。

可以相当容易地添加更多令牌和处理步骤。多字符标记可以变得有趣,特别是如果你去3或字符。

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