如果不使用eval,我无法理解它是如何工作的 - 这背后的秘密是什么?
编辑:有人可以提供一个关于如何将树结构转换为对象的简单示例吗?
答案 0 :(得分:9)
JSON有一个well defined grammar,用于构造一个树,然后将其转换为一个对象。
答案 1 :(得分:3)
获取Douglas Crockford的书, Javascript:Good Parts 。附录E包括实现JSON解析器的代码。它不使用eval。
答案 2 :(得分:2)
我不知道具体细节,但这并不难。只是读取字符和子字符串的智能组合,解释它们的含义并在您执行操作时构建数据数组。像任何其他解析器一样。
答案 3 :(得分:2)
没有秘密。您如何看待eval()的实施?如果你必须解析JSON数据,它会使用你必须使用的相同技术,即有效地重新实现eval()的一部分。
答案 4 :(得分:2)
看看我的解析器是个好主意。它并不完美,但代码很容易理解。
public static JsonStructure Parse(string jsonText)
{
var result = default(JsonStructure);
var structureStack = new Stack<JsonStructure>();
var keyStack = new Stack<string>();
var current = default(JsonStructure);
var currentState = ParserState.Begin;
var key = default(string);
var value = default(object);
foreach (var token in Lexer.Tokenize(jsonText))
{
switch (currentState)
{
case ParserState.Begin:
switch (token.Type)
{
case TokenType.BeginObject:
currentState = ParserState.Name;
current = result = new JsonObject();
break;
case TokenType.BeginArray:
currentState = ParserState.Value;
current = result = new JsonArray();
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.Name:
switch (token.Type)
{
case TokenType.String:
currentState = ParserState.NameSeparator;
key = (string)token.Value;
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.NameSeparator:
switch (token.Type)
{
case TokenType.NameSeparator:
currentState = ParserState.Value;
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.Value:
switch (token.Type)
{
case TokenType.Number:
case TokenType.String:
case TokenType.True:
case TokenType.False:
case TokenType.Null:
currentState = ParserState.ValueSeparator;
value = token.Value;
break;
case TokenType.BeginObject:
structureStack.Push(current);
keyStack.Push(key);
currentState = ParserState.Name;
current = new JsonObject();
break;
case TokenType.BeginArray:
structureStack.Push(current);
currentState = ParserState.Value;
current = new JsonArray();
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.ValueSeparator:
var jsonObject = (current as JsonObject);
var jsonArray = (current as JsonArray);
if (jsonObject != null)
{
jsonObject.Add(key, value);
currentState = ParserState.Name;
}
if (jsonArray != null)
{
jsonArray.Add(value);
currentState = ParserState.Value;
}
switch (token.Type)
{
case TokenType.EndObject:
case TokenType.EndArray:
currentState = ParserState.End;
break;
case TokenType.ValueSeparator:
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.End:
switch (token.Type)
{
case TokenType.EndObject:
case TokenType.EndArray:
case TokenType.ValueSeparator:
var previous = structureStack.Pop();
var previousJsonObject = (previous as JsonObject);
var previousJsonArray = (previous as JsonArray);
if (previousJsonObject != null)
{
previousJsonObject.Add(keyStack.Pop(), current);
currentState = ParserState.Name;
}
if (previousJsonArray != null)
{
previousJsonArray.Add(current);
currentState = ParserState.Value;
}
if (token.Type != TokenType.ValueSeparator)
{
currentState = ParserState.End;
}
current = previous;
break;
default:
throw new JsonException(token, currentState);
}
break;
default:
break;
}
}
return result;
}
答案 5 :(得分:1)
如何将带有json的字符串转换为没有eval的对象的简单示例:
var txt='[\'one\',\'two\']';
var re1='(\\[)'; // Any Single Character 1
var re2='(\\\'.*?\\\')'; // Single Quote String 1
var re3='(,)'; // Any Single Character 2
var re4='(\\\'.*?\\\')'; // Single Quote String 2
var re5='(\\])'; // Any Single Character 3
var p = new RegExp(re1+re2+re3+re4+re5,["i"]);
var m = p.exec(txt);
if (m != null)
{
var c1=m[1];
var s1=m[2];
var c2=m[3];
var s2=m[4];
var c3=m[5];
return [s1, s2];
}
return null;
是的,这是一种可怕的方式,但它完成了它对该字符串的要求:p
答案 6 :(得分:0)
JSON是数据的原生表示。它只是JavaScript内置对象格式的创造性实现。作为原生,它根本不需要“解析”(在程序员需要担心这样做的意义上)。