Exemplo n.º 1
0
        private static object ParseObject(Type type, string json)
        {
            var instance = FormatterServices.GetUninitializedObject(type);

            //The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
            var elems = JSONParser.Split(json);

            if (elems.Count % 2 != 0)
            {
                return(instance);
            }

            Dictionary <string, FieldInfo>    nameToField;
            Dictionary <string, PropertyInfo> nameToProperty;

            if (!JSONParser.fieldInfoCache.TryGetValue(type, out nameToField))
            {
                nameToField = JSONParser.CreateMemberNameDictionary(type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy));
                JSONParser.fieldInfoCache.Add(type, nameToField);
            }

            if (!JSONParser.propertyInfoCache.TryGetValue(type, out nameToProperty))
            {
                nameToProperty = JSONParser.CreateMemberNameDictionary(type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy));
                JSONParser.propertyInfoCache.Add(type, nameToProperty);
            }

            for (var i = 0; i < elems.Count; i += 2)
            {
                if (elems[i].Length <= 2)
                {
                    continue;
                }

                var key   = elems[i].Substring(1, elems[i].Length - 2);
                var value = elems[i + 1];

                FieldInfo    fieldInfo;
                PropertyInfo propertyInfo;
                if (nameToField.TryGetValue(key, out fieldInfo))
                {
                    fieldInfo.SetValue(instance, JSONParser.ParseValue(fieldInfo.FieldType, value));
                }
                else if (nameToProperty.TryGetValue(key, out propertyInfo))
                {
                    propertyInfo.SetValue(instance, JSONParser.ParseValue(propertyInfo.PropertyType, value), null);
                }
            }

            return(instance);
        }
Exemplo n.º 2
0
        public static object FromJson(string json, System.Type type)
        {
            // Initialize, if needed, the ThreadStatic variables
            if (JSONParser.propertyInfoCache == null)
            {
                JSONParser.propertyInfoCache = new Dictionary <Type, Dictionary <string, PropertyInfo> >();
            }

            if (JSONParser.fieldInfoCache == null)
            {
                JSONParser.fieldInfoCache = new Dictionary <Type, Dictionary <string, FieldInfo> >();
            }

            if (JSONParser.stringBuilder == null)
            {
                JSONParser.stringBuilder = new StringBuilder();
            }

            if (JSONParser.splitArrayPool == null)
            {
                JSONParser.splitArrayPool = new Stack <List <string> >();
            }

            //Remove all whitespace not within strings to make parsing simpler
            JSONParser.stringBuilder.Length = 0;
            for (var i = 0; i < json.Length; i++)
            {
                var c = json[i];
                if (c == '"')
                {
                    i = JSONParser.AppendUntilStringEnd(true, i, json);
                    continue;
                }

                if (char.IsWhiteSpace(c))
                {
                    continue;
                }

                JSONParser.stringBuilder.Append(c);
            }

            //Parse the thing!
            return(JSONParser.ParseValue(type, JSONParser.stringBuilder.ToString()));
        }
Exemplo n.º 3
0
        internal static object ParseValue(Type type, string json)
        {
            {
                var resJson = json;
                if (resJson[0] == '"')
                {
                    resJson = resJson.Substring(1, resJson.Length - 2);
                }

                foreach (var parser in ME.ECS.DataConfigGenerator.DataConfigGenerator.parsers)
                {
                    if (parser.IsValid(type) == true)
                    {
                        try {
                            if (parser.Parse(resJson, type, out var result) == true)
                            {
                                return(result);
                            }

                            //if (parser.Parse(data, componentType, fieldName, fieldType, out result) == true) return true;
                        } catch (System.Exception ex) {
                            UnityEngine.Debug.LogError($"Parser `{parser}` failed with exception: {ex.Message}");
                        }
                    }
                }
            }

            if (type == typeof(string))
            {
                if (json.Length <= 2)
                {
                    return(string.Empty);
                }

                var parseStringBuilder = new StringBuilder(json.Length);
                for (var i = 1; i < json.Length - 1; ++i)
                {
                    if (json[i] == '\\' && i + 1 < json.Length - 1)
                    {
                        var 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(parseStringBuilder.ToString());
            }

            if (type.IsPrimitive)
            {
                var result = Convert.ChangeType(json, type, System.Globalization.CultureInfo.InvariantCulture);
                return(result);
            }

            if (type == typeof(decimal))
            {
                decimal result;
                decimal.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out result);
                return(result);
            }

            if (json == "null")
            {
                return(null);
            }

            if (type.IsEnum)
            {
                if (json[0] == '"')
                {
                    json = json.Substring(1, json.Length - 2);
                }

                try {
                    return(Enum.Parse(type, json, false));
                } catch {
                    return(0);
                }
            }

            if (type.IsArray)
            {
                var arrayType = type.GetElementType();
                if (json[0] != '[' || json[json.Length - 1] != ']')
                {
                    return(null);
                }

                var elems    = JSONParser.Split(json);
                var newArray = Array.CreateInstance(arrayType, elems.Count);
                for (var i = 0; i < elems.Count; i++)
                {
                    newArray.SetValue(JSONParser.ParseValue(arrayType, elems[i]), i);
                }

                JSONParser.splitArrayPool.Push(elems);
                return(newArray);
            }

            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List <>))
            {
                var listType = type.GetGenericArguments()[0];
                if (json[0] != '[' || json[json.Length - 1] != ']')
                {
                    return(null);
                }

                var elems = JSONParser.Split(json);
                var list  = (IList)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count });
                for (var i = 0; i < elems.Count; i++)
                {
                    list.Add(JSONParser.ParseValue(listType, elems[i]));
                }

                JSONParser.splitArrayPool.Push(elems);
                return(list);
            }

            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary <,>))
            {
                Type keyType, valueType;
                {
                    var 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(null);
                }

                //Must be a valid dictionary element
                if (json[0] != '{' || json[json.Length - 1] != '}')
                {
                    return(null);
                }

                //The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
                var elems = JSONParser.Split(json);
                if (elems.Count % 2 != 0)
                {
                    return(null);
                }

                var dictionary = (IDictionary)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count / 2 });
                for (var i = 0; i < elems.Count; i += 2)
                {
                    if (elems[i].Length <= 2)
                    {
                        continue;
                    }

                    var keyValue = elems[i].Substring(1, elems[i].Length - 2);
                    var val      = JSONParser.ParseValue(valueType, elems[i + 1]);
                    dictionary[keyValue] = val;
                }

                return(dictionary);
            }

            if (type == typeof(object))
            {
                return(JSONParser.ParseAnonymousValue(json));
            }

            if (json[0] == '{' && json[json.Length - 1] == '}')
            {
                return(JSONParser.ParseObject(type, json));
            }

            return(null);
        }