Exemplo n.º 1
0
        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));
        }