internal static JsonToken ParseToken(Type type, string json) { if (JSONUtilities.IsNullableType(type)) { type = Nullable.GetUnderlyingType(type); } if (type == typeof(string)) { if (json.Length <= 2) { return(new JsonToken(JsonTokenType.String, String.Empty)); } StringBuilder parseStringBuilder = new StringBuilder(json.Length); for (int i = 1; i < json.Length - 1; ++i) { if (json[i] == '\\' && i + 1 < json.Length - 1) { int j = "\"\\nrtbf/".IndexOf(json[i + 1]); if (j >= 0) { parseStringBuilder.Append("\"\\\n\r\t\b\f/"[j]); ++i; continue; } if (json[i + 1] == 'u' && i + 5 < json.Length - 1) { UInt32 c = 0; if (UInt32.TryParse(json.Substring(i + 2, 4), System.Globalization.NumberStyles.AllowHexSpecifier, null, out c)) { parseStringBuilder.Append((char)c); i += 5; continue; } } } parseStringBuilder.Append(json[i]); } return(new JsonToken(JsonTokenType.String, parseStringBuilder.ToString())); } if (type.IsPrimitive) { var tokenType = GetTokenTypeForPrimitive(type); var result = new object(); if (tokenType == JsonTokenType.Integer) { result = Convert.ChangeType(json, typeof(long), System.Globalization.CultureInfo.InvariantCulture); } else { result = Convert.ChangeType(json, type, System.Globalization.CultureInfo.InvariantCulture); } return(new JsonToken(tokenType, result)); } if (type == typeof(decimal)) { float result; float.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out result); return(new JsonToken(JsonTokenType.Float, result)); } if (json == "null") { return(new JsonToken(JsonTokenType.Null, null)); } if (type.IsEnum) { if (json[0] == '"') { json = json.Substring(1, json.Length - 2); } try { if (long.TryParse(json, out var value)) { return(new JsonToken(JsonTokenType.Integer, value)); } else { return(new JsonToken(JsonTokenType.Integer, Convert.ToInt64(Enum.Parse(type, json, false)))); } } catch { return(new JsonToken(JsonTokenType.Integer, 0L)); } } if (type == typeof(DateTime)) { if (json[0] == '"') { json = json.Substring(1, json.Length - 2).Replace("\\", ""); } return(new JsonToken(JsonTokenType.String, json)); } if (type == typeof(Byte[])) { // treat this as a string if (json[0] == '"') { json = json.Substring(1, json.Length - 2); } return(new JsonToken(JsonTokenType.String, json)); } if (type.IsArray) { Type arrayType = type.GetElementType(); if (json[0] != '[' || json[json.Length - 1] != ']') { return(new JsonToken(JsonTokenType.Null, null)); } List <string> elems = Split(json); var array = new JsonToken[elems.Count]; for (int i = 0; i < elems.Count; i++) { array[i] = ParseToken(arrayType, elems[i]); } splitArrayPool.Push(elems); return(new JsonToken(JsonTokenType.Array, array)); } if (type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList <>))) { var generic = type.GetInterfaces().FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList <>)); Type listType = generic.GetGenericArguments()[0]; if (json[0] != '[' || json[json.Length - 1] != ']') { return(new JsonToken(JsonTokenType.Null, null)); } List <string> elems = Split(json); var array = new JsonToken[elems.Count]; for (int i = 0; i < elems.Count; i++) { array[i] = ParseToken(listType, elems[i]); } splitArrayPool.Push(elems); return(new JsonToken(JsonTokenType.Array, array)); } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary <,>)) { Type keyType, valueType; { Type[] args = type.GetGenericArguments(); keyType = args[0]; valueType = args[1]; } //Refuse to parse dictionary keys that aren't of type string if (keyType != typeof(string)) { return(new JsonToken(JsonTokenType.Null, null)); } //Must be a valid dictionary element if (json[0] != '{' || json[json.Length - 1] != '}') { return(new JsonToken(JsonTokenType.Null, null)); } //The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON List <string> elems = Split(json); if (elems.Count % 2 != 0) { return(new JsonToken(JsonTokenType.Null, null)); } var token = new JsonToken(JsonTokenType.Object, null); for (int i = 0; i < elems.Count; i += 2) { if (elems[i].Length <= 2) { continue; } string keyValue = elems[i].Substring(1, elems[i].Length - 2); token.AddKey(keyValue, ParseToken(valueType, elems[i + 1])); } return(token); } if (type == typeof(object)) { return(ParseAnonymousToken(json)); } if (json[0] == '{' && json[json.Length - 1] == '}') { return(ParseObjectToken(type, json)); } return(new JsonToken(JsonTokenType.Null, null)); }