网上已经有很多JSON的反序列化的代码了,但自以为自己能写出更好的,所以就写了一个这方面的东西.实现的思路是,先把JSON字符串分析成JSON结点树,再根据传进来的实体的类型从结点树上取内容.
核心算法如下:
核心算法如下:
构建分析树#region 构建分析树
private Tree<JSONNode> ReadTokens(char[] jsonChars)
{
Tree<JSONNode> rootNode = new Tree<JSONNode>();
TreeNode<JSONNode> currentNode = rootNode;
int curPos = 0;
int index = 0;
bool isKey = false;
NextLoop:
while (index < jsonChars.Length)
{
switch (jsonChars[index])
{
字符串#region 字符串
case '"':
{
index++;
curPos = index;
while (index < jsonChars.Length)
{
if (jsonChars[index].Equals('"'))
{
if (!jsonChars[index - 1].Equals('\\'))
{
if (curPos < index - 1)
{
JSONNode node = new JSONNode(JSONTokenId.StringLiteral ,curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(node);
}
else
{
currentNode.AddChild(node);
}
}
index++;
break;
}
else
{
int p = index - 1;
while (p > curPos && jsonChars[p].Equals('\\')) { p--; }
if ((index - p) % 2 == 1)
{
if (curPos < index - 1)
{
JSONNode node = new JSONNode(JSONTokenId.StringLiteral,curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(node);
}
else
{
currentNode.AddChild(node);
}
}
index++;
break;
}
}
}
index++;
}
break;
}
#endregion
case '{':
{
index++;
JSONNode node = new JSONNode(JSONTokenId.ObjectLiteral);
currentNode = currentNode.AddChild(node);
isKey = true;
break;
}
case '[':
{
index++;
JSONNode node = new JSONNode(JSONTokenId.ArrayLiteral);
currentNode = currentNode.AddChild(node);
break;
}
case ']':
{
index++;
currentNode = currentNode.Parent;
break;
}
case '}':
{
index++;
currentNode = currentNode.Parent.Parent;
isKey = false;
break;
}
case ':':
{
index++;
if (currentNode.Parent.Content != null && currentNode.Parent.Content.TokenId == JSONTokenId.ObjectLiteral)
{
isKey = false;
}
break;
}
case ',':
{
index++;
if (currentNode.Parent.Content !=null && currentNode.Parent.Content.TokenId == JSONTokenId.ObjectLiteral)
{
isKey = true;
currentNode = currentNode.Parent;
}
break;
}
数字#region 数字
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
{
curPos = index;
JSONTokenId numKind = JSONTokenId.IntLiteral;
bool isReal = false;
if (jsonChars[index].Equals('.'))
{
index++;
if (index < jsonChars.Length && (jsonChars[index] >= '0' && jsonChars[index] <= '9'))
{
numKind = JSONTokenId.RealLiteral;
isReal = true;
}
}
bool isNum = true;
if (index < jsonChars.Length && jsonChars[index].Equals('0'))
{
index++;
if (index < jsonChars.Length && (jsonChars[index].Equals('x') || jsonChars[index].Equals('X')))
{
isNum = true;
index++;
while (index < jsonChars.Length && isNum)
{
switch (jsonChars[index])
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
{
index++;
break;
}
default:
{
isNum = false;
break;
}
}
}
if (index < jsonChars.Length && (jsonChars[index].Equals('l') || jsonChars[index].Equals('L')))
{
index++;
numKind = JSONTokenId.LongLiteral;
if (index < jsonChars.Length && (jsonChars[index].Equals('u') || jsonChars[index].Equals('U')))
{
index++;
numKind = JSONTokenId.ULongLiteral;
}
}
else if (index < jsonChars.Length && (jsonChars[index].Equals('u') || jsonChars[index].Equals('U')))
{
index++;
numKind = JSONTokenId.UIntLiteral;
if (index < jsonChars.Length && (jsonChars[index].Equals('l') || jsonChars[index].Equals('L')))
{
index++;
numKind = JSONTokenId.ULongLiteral;
}
}
JSONNode node = new JSONNode(numKind, curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(node);
}
else
{
currentNode.AddChild(node);
}
break;
}
}
isNum = true;
while (index < jsonChars.Length && isNum)
{
switch (jsonChars[index])
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
index++;
break;
}
case '.':
{
if (isReal)
{
numKind = JSONTokenId.RealLiteral;
JSONNode node = new JSONNode(numKind, curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(node);
}
else
{
currentNode.AddChild(node);
}
goto NextLoop;
}
index++;
if (index < jsonChars.Length && (jsonChars[index] < '0' || jsonChars[index] > '9'))
{
JSONNode node = new JSONNode(numKind, curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(node);
}
else
{
currentNode.AddChild(node);
}
goto NextLoop;
}
else
{
numKind = JSONTokenId.RealLiteral;
isReal = true;
}
index++;
break;
}
default:
{
isNum = false;
break;
}
}
}
if (index < jsonChars.Length)
{
if (jsonChars[index].Equals('e') || jsonChars[index].Equals('E'))
{
index++;
numKind = JSONTokenId.RealLiteral;
if (index < jsonChars.Length && (jsonChars[index].Equals('+') || jsonChars[index].Equals('-')))
{
index++;
}
isNum = true;
while (index < jsonChars.Length && isNum)
{
switch (jsonChars[index])
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
index++;
break;
}
default:
{
isNum = false;
break;
}
}
}
}
else if (jsonChars[index].Equals('d') || jsonChars[index].Equals('D') ||
jsonChars[index].Equals('f') || jsonChars[index].Equals('F') ||
jsonChars[index].Equals('m') || jsonChars[index].Equals('M')
)
{
index++;
numKind = JSONTokenId.RealLiteral;
}
else if (jsonChars[index].Equals('l') || jsonChars[index].Equals('L'))
{
index++;
numKind = JSONTokenId.LongLiteral;
if (index < jsonChars.Length && (jsonChars[index].Equals('u') || jsonChars[index].Equals('U')))
{
index++;
numKind = JSONTokenId.ULongLiteral;
}
}
else if (jsonChars[index].Equals('u') || jsonChars[index].Equals('U'))
{
index++;
numKind = JSONTokenId.UIntLiteral;
if (index < jsonChars.Length && (jsonChars[index].Equals('l') || jsonChars[index].Equals('L')))
{
index++;
numKind = JSONTokenId.ULongLiteral;
}
}
}
JSONNode numNode = new JSONNode(numKind, curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(numNode);
}
else
{
currentNode.AddChild(numNode);
}
break;
}
#endregion
default:
{
关键词#region 关键词
switch (jsonChars[index])
{
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case '_':
{
curPos = index;
index++;
bool endIdent = false;
while (index < jsonChars.Length && !endIdent)
{
switch (jsonChars[index])
{
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case '_':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
index++;
break;
}
default:
{
endIdent = true;
break;
}
}
}
if (curPos < index)
{
JSONNode node = new JSONNode(JSONTokenId.StringLiteral,curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(node);
}
else
{
currentNode.AddChild(node);
}
}
break;
}
default:
{
index++;
break;
}
}
#endregion
break;
}
}
}
return rootNode;
}
#endregion
private Tree<JSONNode> ReadTokens(char[] jsonChars)
{
Tree<JSONNode> rootNode = new Tree<JSONNode>();
TreeNode<JSONNode> currentNode = rootNode;
int curPos = 0;
int index = 0;
bool isKey = false;
NextLoop:
while (index < jsonChars.Length)
{
switch (jsonChars[index])
{
字符串#region 字符串
case '"':
{
index++;
curPos = index;
while (index < jsonChars.Length)
{
if (jsonChars[index].Equals('"'))
{
if (!jsonChars[index - 1].Equals('\\'))
{
if (curPos < index - 1)
{
JSONNode node = new JSONNode(JSONTokenId.StringLiteral ,curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(node);
}
else
{
currentNode.AddChild(node);
}
}
index++;
break;
}
else
{
int p = index - 1;
while (p > curPos && jsonChars[p].Equals('\\')) { p--; }
if ((index - p) % 2 == 1)
{
if (curPos < index - 1)
{
JSONNode node = new JSONNode(JSONTokenId.StringLiteral,curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(node);
}
else
{
currentNode.AddChild(node);
}
}
index++;
break;
}
}
}
index++;
}
break;
}
#endregion
case '{':
{
index++;
JSONNode node = new JSONNode(JSONTokenId.ObjectLiteral);
currentNode = currentNode.AddChild(node);
isKey = true;
break;
}
case '[':
{
index++;
JSONNode node = new JSONNode(JSONTokenId.ArrayLiteral);
currentNode = currentNode.AddChild(node);
break;
}
case ']':
{
index++;
currentNode = currentNode.Parent;
break;
}
case '}':
{
index++;
currentNode = currentNode.Parent.Parent;
isKey = false;
break;
}
case ':':
{
index++;
if (currentNode.Parent.Content != null && currentNode.Parent.Content.TokenId == JSONTokenId.ObjectLiteral)
{
isKey = false;
}
break;
}
case ',':
{
index++;
if (currentNode.Parent.Content !=null && currentNode.Parent.Content.TokenId == JSONTokenId.ObjectLiteral)
{
isKey = true;
currentNode = currentNode.Parent;
}
break;
}
数字#region 数字
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
{
curPos = index;
JSONTokenId numKind = JSONTokenId.IntLiteral;
bool isReal = false;
if (jsonChars[index].Equals('.'))
{
index++;
if (index < jsonChars.Length && (jsonChars[index] >= '0' && jsonChars[index] <= '9'))
{
numKind = JSONTokenId.RealLiteral;
isReal = true;
}
}
bool isNum = true;
if (index < jsonChars.Length && jsonChars[index].Equals('0'))
{
index++;
if (index < jsonChars.Length && (jsonChars[index].Equals('x') || jsonChars[index].Equals('X')))
{
isNum = true;
index++;
while (index < jsonChars.Length && isNum)
{
switch (jsonChars[index])
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
{
index++;
break;
}
default:
{
isNum = false;
break;
}
}
}
if (index < jsonChars.Length && (jsonChars[index].Equals('l') || jsonChars[index].Equals('L')))
{
index++;
numKind = JSONTokenId.LongLiteral;
if (index < jsonChars.Length && (jsonChars[index].Equals('u') || jsonChars[index].Equals('U')))
{
index++;
numKind = JSONTokenId.ULongLiteral;
}
}
else if (index < jsonChars.Length && (jsonChars[index].Equals('u') || jsonChars[index].Equals('U')))
{
index++;
numKind = JSONTokenId.UIntLiteral;
if (index < jsonChars.Length && (jsonChars[index].Equals('l') || jsonChars[index].Equals('L')))
{
index++;
numKind = JSONTokenId.ULongLiteral;
}
}
JSONNode node = new JSONNode(numKind, curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(node);
}
else
{
currentNode.AddChild(node);
}
break;
}
}
isNum = true;
while (index < jsonChars.Length && isNum)
{
switch (jsonChars[index])
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
index++;
break;
}
case '.':
{
if (isReal)
{
numKind = JSONTokenId.RealLiteral;
JSONNode node = new JSONNode(numKind, curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(node);
}
else
{
currentNode.AddChild(node);
}
goto NextLoop;
}
index++;
if (index < jsonChars.Length && (jsonChars[index] < '0' || jsonChars[index] > '9'))
{
JSONNode node = new JSONNode(numKind, curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(node);
}
else
{
currentNode.AddChild(node);
}
goto NextLoop;
}
else
{
numKind = JSONTokenId.RealLiteral;
isReal = true;
}
index++;
break;
}
default:
{
isNum = false;
break;
}
}
}
if (index < jsonChars.Length)
{
if (jsonChars[index].Equals('e') || jsonChars[index].Equals('E'))
{
index++;
numKind = JSONTokenId.RealLiteral;
if (index < jsonChars.Length && (jsonChars[index].Equals('+') || jsonChars[index].Equals('-')))
{
index++;
}
isNum = true;
while (index < jsonChars.Length && isNum)
{
switch (jsonChars[index])
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
index++;
break;
}
default:
{
isNum = false;
break;
}
}
}
}
else if (jsonChars[index].Equals('d') || jsonChars[index].Equals('D') ||
jsonChars[index].Equals('f') || jsonChars[index].Equals('F') ||
jsonChars[index].Equals('m') || jsonChars[index].Equals('M')
)
{
index++;
numKind = JSONTokenId.RealLiteral;
}
else if (jsonChars[index].Equals('l') || jsonChars[index].Equals('L'))
{
index++;
numKind = JSONTokenId.LongLiteral;
if (index < jsonChars.Length && (jsonChars[index].Equals('u') || jsonChars[index].Equals('U')))
{
index++;
numKind = JSONTokenId.ULongLiteral;
}
}
else if (jsonChars[index].Equals('u') || jsonChars[index].Equals('U'))
{
index++;
numKind = JSONTokenId.UIntLiteral;
if (index < jsonChars.Length && (jsonChars[index].Equals('l') || jsonChars[index].Equals('L')))
{
index++;
numKind = JSONTokenId.ULongLiteral;
}
}
}
JSONNode numNode = new JSONNode(numKind, curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(numNode);
}
else
{
currentNode.AddChild(numNode);
}
break;
}
#endregion
default:
{
关键词#region 关键词
switch (jsonChars[index])
{
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case '_':
{
curPos = index;
index++;
bool endIdent = false;
while (index < jsonChars.Length && !endIdent)
{
switch (jsonChars[index])
{
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case '_':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
index++;
break;
}
default:
{
endIdent = true;
break;
}
}
}
if (curPos < index)
{
JSONNode node = new JSONNode(JSONTokenId.StringLiteral,curPos, index);
if (isKey)
{
currentNode = currentNode.AddChild(node);
}
else
{
currentNode.AddChild(node);
}
}
break;
}
default:
{
index++;
break;
}
}
#endregion
break;
}
}
}
return rootNode;
}
#endregion