From 9322abab3e8792bdf1a1a8d8b3efd4689a1ddd23 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 12 Nov 2021 15:04:53 +0000 Subject: [PATCH] Changed parser from JSONUtility to TinyJson --- Code/JSONParser/JSONParser.cs | 377 ++++++++++++++++++++++++++++++++++ Code/Program.cs | 4 +- Code/Utils/CDUtils.cs | 6 +- JSONLoader/JSONLoader.dll | Bin 25600 -> 30208 bytes manifest.json | 2 +- 5 files changed, 383 insertions(+), 6 deletions(-) create mode 100644 Code/JSONParser/JSONParser.cs diff --git a/Code/JSONParser/JSONParser.cs b/Code/JSONParser/JSONParser.cs new file mode 100644 index 0000000..c84db37 --- /dev/null +++ b/Code/JSONParser/JSONParser.cs @@ -0,0 +1,377 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.Serialization; +using System.Text; + +namespace TinyJson +{ + // Really simple JSON parser in ~300 lines + // - Attempts to parse JSON files with minimal GC allocation + // - Nice and simple "[1,2,3]".FromJson>() API + // - Classes and structs can be parsed too! + // class Foo { public int Value; } + // "{\"Value\":10}".FromJson() + // - Can parse JSON without type information into Dictionary and List e.g. + // "[1,2,3]".FromJson().GetType() == typeof(List) + // "{\"Value\":10}".FromJson().GetType() == typeof(Dictionary) + // - No JIT Emit support to support AOT compilation on iOS + // - Attempts are made to NOT throw an exception if the JSON is corrupted or invalid: returns null instead. + // - Only public fields and property setters on classes/structs will be written to + // + // Limitations: + // - No JIT Emit support to parse structures quickly + // - Limited to parsing <2GB JSON files (due to int.MaxValue) + // - Parsing of abstract classes or interfaces is NOT supported and will throw an exception. + public static class JSONParser + { + [ThreadStatic] static Stack> splitArrayPool; + [ThreadStatic] static StringBuilder stringBuilder; + [ThreadStatic] static Dictionary> fieldInfoCache; + [ThreadStatic] static Dictionary> propertyInfoCache; + + public static T FromJson(this string json) + { + // Initialize, if needed, the ThreadStatic variables + if (propertyInfoCache == null) propertyInfoCache = new Dictionary>(); + if (fieldInfoCache == null) fieldInfoCache = new Dictionary>(); + if (stringBuilder == null) stringBuilder = new StringBuilder(); + if (splitArrayPool == null) splitArrayPool = new Stack>(); + + //Remove all whitespace not within strings to make parsing simpler + stringBuilder.Length = 0; + for (int i = 0; i < json.Length; i++) + { + char c = json[i]; + if (c == '"') + { + i = AppendUntilStringEnd(true, i, json); + continue; + } + if (char.IsWhiteSpace(c)) + continue; + + stringBuilder.Append(c); + } + + //Parse the thing! + return (T)ParseValue(typeof(T), stringBuilder.ToString()); + } + + static int AppendUntilStringEnd(bool appendEscapeCharacter, int startIdx, string json) + { + stringBuilder.Append(json[startIdx]); + for (int i = startIdx + 1; i < json.Length; i++) + { + if (json[i] == '\\') + { + if (appendEscapeCharacter) + stringBuilder.Append(json[i]); + stringBuilder.Append(json[i + 1]); + i++;//Skip next character as it is escaped + } + else if (json[i] == '"') + { + stringBuilder.Append(json[i]); + return i; + } + else + stringBuilder.Append(json[i]); + } + return json.Length - 1; + } + + //Splits { :, : } and [ , ] into a list of strings + static List Split(string json) + { + List splitArray = splitArrayPool.Count > 0 ? splitArrayPool.Pop() : new List(); + splitArray.Clear(); + if (json.Length == 2) + return splitArray; + int parseDepth = 0; + stringBuilder.Length = 0; + for (int i = 1; i < json.Length - 1; i++) + { + switch (json[i]) + { + case '[': + case '{': + parseDepth++; + break; + case ']': + case '}': + parseDepth--; + break; + case '"': + i = AppendUntilStringEnd(true, i, json); + continue; + case ',': + case ':': + if (parseDepth == 0) + { + splitArray.Add(stringBuilder.ToString()); + stringBuilder.Length = 0; + continue; + } + break; + } + + stringBuilder.Append(json[i]); + } + + splitArray.Add(stringBuilder.ToString()); + + return splitArray; + } + + internal static object ParseValue(Type type, string json) + { + if (type == typeof(string)) + { + if (json.Length <= 2) + return 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 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 (type == typeof(DateTime)) + { + DateTime result; + DateTime.TryParse(json.Replace("\"",""), System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, 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) + { + Type arrayType = type.GetElementType(); + if (json[0] != '[' || json[json.Length - 1] != ']') + return null; + + List elems = Split(json); + Array newArray = Array.CreateInstance(arrayType, elems.Count); + for (int i = 0; i < elems.Count; i++) + newArray.SetValue(ParseValue(arrayType, elems[i]), i); + splitArrayPool.Push(elems); + return newArray; + } + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>)) + { + Type listType = type.GetGenericArguments()[0]; + if (json[0] != '[' || json[json.Length - 1] != ']') + return null; + + List elems = Split(json); + var list = (IList)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count }); + for (int i = 0; i < elems.Count; i++) + list.Add(ParseValue(listType, elems[i])); + splitArrayPool.Push(elems); + return list; + } + 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 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 + List elems = 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 (int i = 0; i < elems.Count; i += 2) + { + if (elems[i].Length <= 2) + continue; + string keyValue = elems[i].Substring(1, elems[i].Length - 2); + object val = ParseValue(valueType, elems[i + 1]); + dictionary[keyValue] = val; + } + return dictionary; + } + if (type == typeof(object)) + { + return ParseAnonymousValue(json); + } + if (json[0] == '{' && json[json.Length - 1] == '}') + { + return ParseObject(type, json); + } + + return null; + } + + static object ParseAnonymousValue(string json) + { + if (json.Length == 0) + return null; + if (json[0] == '{' && json[json.Length - 1] == '}') + { + List elems = Split(json); + if (elems.Count % 2 != 0) + return null; + var dict = new Dictionary(elems.Count / 2); + for (int i = 0; i < elems.Count; i += 2) + dict[elems[i].Substring(1, elems[i].Length - 2)] = ParseAnonymousValue(elems[i + 1]); + return dict; + } + if (json[0] == '[' && json[json.Length - 1] == ']') + { + List items = Split(json); + var finalList = new List(items.Count); + for (int i = 0; i < items.Count; i++) + finalList.Add(ParseAnonymousValue(items[i])); + return finalList; + } + if (json[0] == '"' && json[json.Length - 1] == '"') + { + string str = json.Substring(1, json.Length - 2); + return str.Replace("\\", string.Empty); + } + if (char.IsDigit(json[0]) || json[0] == '-') + { + if (json.Contains(".")) + { + double result; + double.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out result); + return result; + } + else + { + int result; + int.TryParse(json, out result); + return result; + } + } + if (json == "true") + return true; + if (json == "false") + return false; + // handles json == "null" as well as invalid JSON + return null; + } + + static Dictionary CreateMemberNameDictionary(T[] members) where T : MemberInfo + { + Dictionary nameToMember = new Dictionary(StringComparer.OrdinalIgnoreCase); + for (int i = 0; i < members.Length; i++) + { + T member = members[i]; + if (member.IsDefined(typeof(IgnoreDataMemberAttribute), true)) + continue; + + string name = member.Name; + if (member.IsDefined(typeof(DataMemberAttribute), true)) + { + DataMemberAttribute dataMemberAttribute = (DataMemberAttribute)Attribute.GetCustomAttribute(member, typeof(DataMemberAttribute), true); + if (!string.IsNullOrEmpty(dataMemberAttribute.Name)) + name = dataMemberAttribute.Name; + } + + nameToMember.Add(name, member); + } + + return nameToMember; + } + + static object ParseObject(Type type, string json) + { + object 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 + List elems = Split(json); + if (elems.Count % 2 != 0) + return instance; + + Dictionary nameToField; + Dictionary nameToProperty; + if (!fieldInfoCache.TryGetValue(type, out nameToField)) + { + nameToField = CreateMemberNameDictionary(type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy)); + fieldInfoCache.Add(type, nameToField); + } + if (!propertyInfoCache.TryGetValue(type, out nameToProperty)) + { + nameToProperty = CreateMemberNameDictionary(type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy)); + propertyInfoCache.Add(type, nameToProperty); + } + + for (int i = 0; i < elems.Count; i += 2) + { + if (elems[i].Length <= 2) + continue; + string key = elems[i].Substring(1, elems[i].Length - 2); + string value = elems[i + 1]; + + FieldInfo fieldInfo; + PropertyInfo propertyInfo; + if (nameToField.TryGetValue(key, out fieldInfo)) + fieldInfo.SetValue(instance, ParseValue(fieldInfo.FieldType, value)); + else if (nameToProperty.TryGetValue(key, out propertyInfo)) + propertyInfo.SetValue(instance, ParseValue(propertyInfo.PropertyType, value), null); + } + + return instance; + } + } +} diff --git a/Code/Program.cs b/Code/Program.cs index 0827ed1..9252cf1 100644 --- a/Code/Program.cs +++ b/Code/Program.cs @@ -22,7 +22,7 @@ public class Plugin : BaseUnityPlugin { private const string PluginGuid = "MADH.inscryption.JSONCardLoader"; private const string PluginName = "JSONCardLoader"; - private const string PluginVersion = "1.3.10.0"; + private const string PluginVersion = "1.4.0.0"; internal static ManualLogSource Log; @@ -59,7 +59,7 @@ private void Awake() if ( card is not null ) { - if ( card.fieldsToEdit.Count > 0 ) + if ( card.fieldsToEdit is not null ) { Log.LogInfo( $"Editing from { fileName }..." ); diff --git a/Code/Utils/CDUtils.cs b/Code/Utils/CDUtils.cs index ec2e554..045fe62 100644 --- a/Code/Utils/CDUtils.cs +++ b/Code/Utils/CDUtils.cs @@ -1,6 +1,6 @@ -using UnityEngine; +using APIPlugin; -using APIPlugin; +using TinyJson; namespace JLPlugin.Utils { @@ -9,7 +9,7 @@ namespace JLPlugin.Utils class CDUtils { public static CardData CreateFromJSON( string jsonString ) - => JsonUtility.FromJson( jsonString ); + => JSONParser.FromJson( jsonString ); public static void GenerateNewCard( CardData card ) { diff --git a/JSONLoader/JSONLoader.dll b/JSONLoader/JSONLoader.dll index 990651252214817471843a8facb969eecd79065e..3f4fecf86fa14e49ea61fe86a300d4cc52293355 100644 GIT binary patch literal 30208 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 BB-8)^ literal 25600 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