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

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

解析JsonValue


private static JsonValue ParseValue(ref Data data)
{
 // 跳过空白字符
 SkipWhiteSpace(ref data);
 var c = data.json[data.index];
 switch (c)
 {
  case '{': 
   // 表示Object
   return ParseObject(ref data);
  case '[':
   // 表示Array
   return ParseArray (ref data);
  case '"':
   // 表示string
   return ParseString(ref data);
  case '0':
  case '1':
  case '2':
  case '3':
  case '4':
  case '5':
  case '6':
  case '7':
  case '8':
  case '9':
  case '-':
   // 表示数值
   return ParseNumber(ref data);
  case 'f': // 表示可能是false
   if 
    (
     data.json[data.index + 1] == 'a' && 
     data.json[data.index + 2] == 'l' &&
     data.json[data.index + 3] == 's' &&
     data.json[data.index + 4] == 'e'
    )
   {
    data.index += 5;
    // 表示是false
    return new JsonValue(JsonType.Bool, false);
   }
   break;
  case 't': // 表示可能是true
   if 
    (
     data.json[data.index + 1] == 'r' && 
     data.json[data.index + 2] == 'u' &&
     data.json[data.index + 3] == 'e'
    )
   {
    data.index += 4;
    // 表示是true
    return new JsonValue(JsonType.Bool, true);
   }
   break;
  case 'n': // 表示可能是null
   if 
    (
     data.json[data.index + 1] == 'u' && 
     data.json[data.index + 2] == 'l' &&
     data.json[data.index + 3] == 'l'
    )
   {
    data.index += 4;
    // 表示可能是null
    return new JsonValue(JsonType.Null, null);
   }
   break;
 }
 // 不能处理了
 throw new Exception(string.Format("Json ParseValue error on char '{0}' index in '{1}' ", c, data.index));
}
ParseValue是解析的主入口,代表着解析JsonValue这个抽象的JSON值,其真实的类型在解析的过程中逐渐具体化。 在剥离掉空白字符之后,就可以很容易的通过单个字符,就判断出其可能的数值类型,而不需要向前或向后检索。 true,false,null 这几个固定的类型,直接就处理掉了,而其它稍微复杂的类型需要使用函数来处理。 这里没有使用if else,而是大量使用了case,是为了提高效率,减少判断次数。

解析JsonObject


private static JsonValue ParseObject(ref Data data)
{
 // Object 对应 C#的Dictionary
 var jsonObject = new Dictionary<string, JsonValue>(JsonObjectInitCapacity);
 // skip '{'
 data.index++;
 do
 {
  // 跳过空白字符
  SkipWhiteSpace(ref data);
  if (data.json[data.index] == '}')
  {
   // 空的Object, "{}"
   break;
  }
  DebugTool.Assert
  (
   data.json[data.index] == '"', 
   "Json ParseObject error, char '{0}' should be '"' ", 
   data.json[data.index]
  );
  // skip '"'
  data.index++;
  var start = data.index;
  // 解析Object的key值
  while (true)
  {
   var c = data.json[data.index++];
   switch (c)
   {
    case '"':
     // check end '"'
     break;
    case '':
     // skip escaped quotes
     data.index++;
     continue;
    default:
     continue;
   }
   // already skip the end '"'
   break;
  }
  // get object key string
  // 扣出key字符串
  var key = data.json.Substring(start, data.index - start - 1);
  // 跳过空白
  SkipWhiteSpace(ref data);
  DebugTool.Assert
  (
   data.json[data.index] == ':', 
   "Json ParseObject error, after key = {0}, char '{1}' should be ':' ", 
   key,
   data.json[data.index]
  );
  // skip ':'
  data.index++;
  // set JsonObject key and value
  // 递归的调用ParseValue获得Object的value值
  jsonObject.Add(key, ParseValue(ref data));
  // 跳过空白
  SkipWhiteSpace(ref data);
  if (data.json[data.index] == ',')
  {
   // Object的下一对KV
   data.index++ ;     
  }
  else
  {
   // 跳过空白
   SkipWhiteSpace(ref data);
   DebugTool.Assert
   (
    data.json[data.index] == '}', 
    "Json ParseObject error, after key = {0}, char '{1}' should be '{2}' ",
    key,
    data.json[data.index],
    '}'
   );
   break;
  }
 }
 while (true);
 // skip '}' and return after '}'
 data.index++;
 return new JsonValue(JsonType.Object, jsonObject);
}