C#实现JSON解析器MojoUnityJson功能(简单且高效)

2019-12-30 19:12:58于海丽

JsonObject类型就简单的对应C#的Dictionary,value是JsonValue类型。当解析完成后,value的类型就是确定的了。

JsonValue是递归的调用ParseValue来处理的,其类型可能是JsonType枚举的任意类型。

解析JsonArray


private static JsonValue ParseArray(ref Data data)
{
 // JsonArray 对应 List
 var jsonArray = new List<JsonValue>(JsonArrayInitCapacity);
 // skip '['
 data.index++;
 do
 {
  // 跳过空白
  SkipWhiteSpace(ref data);
  if (data.json[data.index] == ']')
  {
   // 空 "[]"
   break;
  }
  // add JsonArray item 
  // 递归处理List每个元素
  jsonArray.Add(ParseValue(ref data));
  // 跳过空白
  SkipWhiteSpace(ref data);
  if (data.json[data.index] == ',')
  {
   // 解析下一个元素
   data.index++;
  }
  else
  {
   // 跳过空白
   SkipWhiteSpace(ref data);
   DebugTool.Assert
   (
    data.json[data.index] == ']', 
    "Json ParseArray error, char '{0}' should be ']' ", 
    data.json[data.index]
   );
   break;
  }
 }
 while (true);
 // skip ']'
 data.index++;
 return new JsonValue(JsonType.Array, jsonArray);
}

JsonArray类型就简单的对应C#的List,element是JsonValue类型。当解析完成后,element的类型就是确定的了。

JsonValue是递归的调用ParseValue来处理的,其类型可能是JsonType枚举的任意类型。

解析string


private static JsonValue ParseString(ref Data data)
{
 // skip '"'
 data.index++;
 var start = data.index;
 string str;
 // 处理字符串
 while (true)
 {
  switch (data.json[data.index++])
  {
   case '"': // 字符串结束
    // check end '"'      
    if (data.sb.Length == 0)
    {
     // 没有使用StringBuilder,直接抠出字符串
     str = data.json.Substring(start, data.index - start - 1);
    }
    else
    {
     // 有特殊字符在StringBuilder
     str = data.sb.Append(data.json, start, data.index - start - 1).ToString();
     // clear for next string
     // 清空字符,供下次使用
     data.sb.Length = 0;
    }
    break;
   case '':
    {
     // check escaped char
     var escapedIndex = data.index;
     char c;
     // 处理各种转义字符
     switch (data.json[data.index++])
     {
      case '"':
       c = '"';
       break;
      case ''':
       c = ''';
       break;
      case '':
       c = '';
       break;
      case '/':
       c = '/';
       break;
      case 'n':
       c = 'n';
       break;
      case 'r':
       c = 'r';
       break;
      case 't':
       c = 't';
       break;
      case 'u':
       // 计算unicode字符的码点
       c = GetUnicodeCodePoint
        (
         data.json[data.index], 
         data.json[data.index + 1], 
         data.json[data.index + 2], 
         data.json[data.index + 3]
        );
       // skip code point
       data.index += 4;
       break;
      default:
       // not support just add in pre string
       continue;
     }
     // add pre string and escaped char
     // 特殊处理的字符和正常的字符,一起放入StringBuilder
     data.sb.Append(data.json, start, escapedIndex - start - 1).Append(c);
     // update pre string start index
     start = data.index;
     continue;
    }
   default:
    continue;
  }
  // already skip the end '"'
  break;
 }
 return new JsonValue(JsonType.String, str);
}