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); }
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())); }
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); }