From 03740e4ee0e893b010827826f3336fbf363bd7c4 Mon Sep 17 00:00:00 2001 From: Dave Black <2200903@wholefoods.com> Date: Mon, 23 Jan 2023 15:33:44 -0600 Subject: [PATCH 1/4] Add thread safety to fix race conditions around usage of static IDictionary instances. Note these should be converted to use ConcurrentDictionary to avoid the performance overhead of using static lock objects. --- src/LitJson/JsonMapper.cs | 893 ++++++++++++++++++++++---------------- 1 file changed, 508 insertions(+), 385 deletions(-) diff --git a/src/LitJson/JsonMapper.cs b/src/LitJson/JsonMapper.cs index 99946cf..f2d7f2b 100644 --- a/src/LitJson/JsonMapper.cs +++ b/src/LitJson/JsonMapper.cs @@ -22,8 +22,8 @@ namespace LitJson internal struct PropertyMetadata { public MemberInfo Info; - public bool IsField; - public Type Type; + public bool IsField; + public Type Type; } @@ -34,10 +34,12 @@ internal struct ArrayMetadata private bool is_list; - public Type ElementType { - get { + public Type ElementType + { + get + { if (element_type == null) - return typeof (JsonData); + return typeof(JsonData); return element_type; } @@ -45,12 +47,14 @@ public Type ElementType { set { element_type = value; } } - public bool IsArray { + public bool IsArray + { get { return is_array; } set { is_array = value; } } - public bool IsList { + public bool IsList + { get { return is_list; } set { is_list = value; } } @@ -65,10 +69,12 @@ internal struct ObjectMetadata private IDictionary properties; - public Type ElementType { - get { + public Type ElementType + { + get + { if (element_type == null) - return typeof (JsonData); + return typeof(JsonData); return element_type; } @@ -76,25 +82,27 @@ public Type ElementType { set { element_type = value; } } - public bool IsDictionary { + public bool IsDictionary + { get { return is_dictionary; } set { is_dictionary = value; } } - public IDictionary Properties { + public IDictionary Properties + { get { return properties; } set { properties = value; } } } - internal delegate void ExporterFunc (object obj, JsonWriter writer); - public delegate void ExporterFunc (T obj, JsonWriter writer); + internal delegate void ExporterFunc(object obj, JsonWriter writer); + public delegate void ExporterFunc(T obj, JsonWriter writer); - internal delegate object ImporterFunc (object input); - public delegate TValue ImporterFunc (TJson input); + internal delegate object ImporterFunc(object input); + public delegate TValue ImporterFunc(TJson input); - public delegate IJsonWrapper WrapperFactory (); + public delegate IJsonWrapper WrapperFactory(); public class JsonMapper @@ -106,196 +114,221 @@ public class JsonMapper private static readonly IDictionary base_exporters_table; private static readonly IDictionary custom_exporters_table; + private static readonly object custom_exporters_table_lock = new Object(); private static readonly IDictionary> base_importers_table; private static readonly IDictionary> custom_importers_table; + private static readonly object custom_importers_table_lock = new Object(); private static readonly IDictionary array_metadata; - private static readonly object array_metadata_lock = new Object (); + private static readonly object array_metadata_lock = new Object(); private static readonly IDictionary> conv_ops; - private static readonly object conv_ops_lock = new Object (); + private static readonly object conv_ops_lock = new Object(); private static readonly IDictionary object_metadata; - private static readonly object object_metadata_lock = new Object (); + private static readonly object object_metadata_lock = new Object(); private static readonly IDictionary> type_properties; - private static readonly object type_properties_lock = new Object (); + private static readonly object type_properties_lock = new Object(); - private static readonly JsonWriter static_writer; - private static readonly object static_writer_lock = new Object (); + private static readonly JsonWriter static_writer; + private static readonly object static_writer_lock = new Object(); #endregion #region Constructors - static JsonMapper () + static JsonMapper() { max_nesting_depth = 100; - array_metadata = new Dictionary (); - conv_ops = new Dictionary> (); - object_metadata = new Dictionary (); + array_metadata = new Dictionary(); + conv_ops = new Dictionary>(); + object_metadata = new Dictionary(); type_properties = new Dictionary> (); + IList>(); - static_writer = new JsonWriter (); + static_writer = new JsonWriter(); datetime_format = DateTimeFormatInfo.InvariantInfo; - base_exporters_table = new Dictionary (); - custom_exporters_table = new Dictionary (); + base_exporters_table = new Dictionary(); + custom_exporters_table = new Dictionary(); base_importers_table = new Dictionary> (); + IDictionary>(); custom_importers_table = new Dictionary> (); + IDictionary>(); - RegisterBaseExporters (); - RegisterBaseImporters (); + RegisterBaseExporters(); + RegisterBaseImporters(); } #endregion #region Private Methods - private static void AddArrayMetadata (Type type) + private static void AddArrayMetadata(Type type) { - if (array_metadata.ContainsKey (type)) + if (array_metadata.ContainsKey(type)) return; - ArrayMetadata data = new ArrayMetadata (); + ArrayMetadata data = new ArrayMetadata(); data.IsArray = type.IsArray; - if (type.GetInterface ("System.Collections.IList") != null) + if (type.GetInterface("System.Collections.IList") != null) data.IsList = true; - foreach (PropertyInfo p_info in type.GetProperties ()) { + foreach (PropertyInfo p_info in type.GetProperties()) + { if (p_info.Name != "Item") continue; - ParameterInfo[] parameters = p_info.GetIndexParameters (); + ParameterInfo[] parameters = p_info.GetIndexParameters(); if (parameters.Length != 1) continue; - if (parameters[0].ParameterType == typeof (int)) + if (parameters[0].ParameterType == typeof(int)) data.ElementType = p_info.PropertyType; } - lock (array_metadata_lock) { - try { - array_metadata.Add (type, data); - } catch (ArgumentException) { + lock (array_metadata_lock) + { + try + { + array_metadata.Add(type, data); + } + catch (ArgumentException) + { return; } } } - private static void AddObjectMetadata (Type type) + private static void AddObjectMetadata(Type type) { - if (object_metadata.ContainsKey (type)) + if (object_metadata.ContainsKey(type)) return; - ObjectMetadata data = new ObjectMetadata (); + ObjectMetadata data = new ObjectMetadata(); - if (type.GetInterface ("System.Collections.IDictionary") != null) + if (type.GetInterface("System.Collections.IDictionary") != null) data.IsDictionary = true; - data.Properties = new Dictionary (); + data.Properties = new Dictionary(); - foreach (PropertyInfo p_info in type.GetProperties ()) { - if (p_info.Name == "Item") { - ParameterInfo[] parameters = p_info.GetIndexParameters (); + foreach (PropertyInfo p_info in type.GetProperties()) + { + if (p_info.Name == "Item") + { + ParameterInfo[] parameters = p_info.GetIndexParameters(); if (parameters.Length != 1) continue; - if (parameters[0].ParameterType == typeof (string)) + if (parameters[0].ParameterType == typeof(string)) data.ElementType = p_info.PropertyType; continue; } - PropertyMetadata p_data = new PropertyMetadata (); + PropertyMetadata p_data = new PropertyMetadata(); p_data.Info = p_info; p_data.Type = p_info.PropertyType; - data.Properties.Add (p_info.Name, p_data); + data.Properties.Add(p_info.Name, p_data); } - foreach (FieldInfo f_info in type.GetFields ()) { - PropertyMetadata p_data = new PropertyMetadata (); + foreach (FieldInfo f_info in type.GetFields()) + { + PropertyMetadata p_data = new PropertyMetadata(); p_data.Info = f_info; p_data.IsField = true; p_data.Type = f_info.FieldType; - data.Properties.Add (f_info.Name, p_data); + data.Properties.Add(f_info.Name, p_data); } - lock (object_metadata_lock) { - try { - object_metadata.Add (type, data); - } catch (ArgumentException) { + lock (object_metadata_lock) + { + try + { + object_metadata.Add(type, data); + } + catch (ArgumentException) + { return; } } } - private static void AddTypeProperties (Type type) + private static void AddTypeProperties(Type type) { - if (type_properties.ContainsKey (type)) + if (type_properties.ContainsKey(type)) return; - IList props = new List (); + IList props = new List(); - foreach (PropertyInfo p_info in type.GetProperties ()) { + foreach (PropertyInfo p_info in type.GetProperties()) + { if (p_info.Name == "Item") continue; - PropertyMetadata p_data = new PropertyMetadata (); + PropertyMetadata p_data = new PropertyMetadata(); p_data.Info = p_info; p_data.IsField = false; - props.Add (p_data); + props.Add(p_data); } - foreach (FieldInfo f_info in type.GetFields ()) { - PropertyMetadata p_data = new PropertyMetadata (); + foreach (FieldInfo f_info in type.GetFields()) + { + PropertyMetadata p_data = new PropertyMetadata(); p_data.Info = f_info; p_data.IsField = true; - props.Add (p_data); + props.Add(p_data); } - lock (type_properties_lock) { - try { - type_properties.Add (type, props); - } catch (ArgumentException) { + lock (type_properties_lock) + { + try + { + type_properties.Add(type, props); + } + catch (ArgumentException) + { return; } } } - private static MethodInfo GetConvOp (Type t1, Type t2) + private static MethodInfo GetConvOp(Type t1, Type t2) { - lock (conv_ops_lock) { - if (! conv_ops.ContainsKey (t1)) - conv_ops.Add (t1, new Dictionary ()); + lock (conv_ops_lock) + { + if (!conv_ops.ContainsKey(t1)) + conv_ops.Add(t1, new Dictionary()); } - if (conv_ops[t1].ContainsKey (t2)) + if (conv_ops[t1].ContainsKey(t2)) return conv_ops[t1][t2]; - MethodInfo op = t1.GetMethod ( + MethodInfo op = t1.GetMethod( "op_Implicit", new Type[] { t2 }); - lock (conv_ops_lock) { - try { - conv_ops[t1].Add (t2, op); - } catch (ArgumentException) { + lock (conv_ops_lock) + { + try + { + conv_ops[t1].Add(t2, op); + } + catch (ArgumentException) + { return conv_ops[t1][t2]; } } @@ -303,9 +336,9 @@ private static MethodInfo GetConvOp (Type t1, Type t2) return op; } - private static object ReadValue (Type inst_type, JsonReader reader) + private static object ReadValue(Type inst_type, JsonReader reader) { - reader.Read (); + reader.Read(); if (reader.Token == JsonToken.ArrayEnd) return null; @@ -313,18 +346,20 @@ private static object ReadValue (Type inst_type, JsonReader reader) Type underlying_type = Nullable.GetUnderlyingType(inst_type); Type value_type = underlying_type ?? inst_type; - if (reader.Token == JsonToken.Null) { - #if NETSTANDARD1_5 + if (reader.Token == JsonToken.Null) + { +#if NETSTANDARD1_5 if (inst_type.IsClass() || underlying_type != null) { return null; } - #else - if (inst_type.IsClass || underlying_type != null) { +#else + if (inst_type.IsClass || underlying_type != null) + { return null; } - #endif +#endif - throw new JsonException (String.Format ( + throw new JsonException(String.Format( "Can't assign null to an instance of type {0}", inst_type)); } @@ -333,148 +368,164 @@ private static object ReadValue (Type inst_type, JsonReader reader) reader.Token == JsonToken.Int || reader.Token == JsonToken.Long || reader.Token == JsonToken.String || - reader.Token == JsonToken.Boolean) { + reader.Token == JsonToken.Boolean) + { - Type json_type = reader.Value.GetType (); + Type json_type = reader.Value.GetType(); - if (value_type.IsAssignableFrom (json_type)) + if (value_type.IsAssignableFrom(json_type)) return reader.Value; // If there's a custom importer that fits, use it - if (custom_importers_table.ContainsKey (json_type) && - custom_importers_table[json_type].ContainsKey ( - value_type)) { - - ImporterFunc importer = - custom_importers_table[json_type][value_type]; - - return importer (reader.Value); + lock (custom_importers_table_lock) + { + if (custom_importers_table.TryGetValue(json_type, out IDictionary customImporterTablesValue) && + customImporterTablesValue.TryGetValue(value_type, out ImporterFunc customImporter)) + { + return customImporter(reader.Value); + } } // Maybe there's a base importer that works - if (base_importers_table.ContainsKey (json_type) && - base_importers_table[json_type].ContainsKey ( - value_type)) { - - ImporterFunc importer = - base_importers_table[json_type][value_type]; - - return importer (reader.Value); + if (base_importers_table.TryGetValue(json_type, out IDictionary baseImporterTablesValue) && + baseImporterTablesValue.TryGetValue(value_type, out ImporterFunc baseImporter)) + { + return baseImporter(reader.Value); } // Maybe it's an enum - #if NETSTANDARD1_5 +#if NETSTANDARD1_5 if (value_type.IsEnum()) return Enum.ToObject (value_type, reader.Value); - #else +#else if (value_type.IsEnum) - return Enum.ToObject (value_type, reader.Value); - #endif + return Enum.ToObject(value_type, reader.Value); +#endif // Try using an implicit conversion operator - MethodInfo conv_op = GetConvOp (value_type, json_type); + MethodInfo conv_op = GetConvOp(value_type, json_type); if (conv_op != null) - return conv_op.Invoke (null, + return conv_op.Invoke(null, new object[] { reader.Value }); // No luck - throw new JsonException (String.Format ( + throw new JsonException(String.Format( "Can't assign value '{0}' (type {1}) to type {2}", reader.Value, json_type, inst_type)); } object instance = null; - if (reader.Token == JsonToken.ArrayStart) { + if (reader.Token == JsonToken.ArrayStart) + { - AddArrayMetadata (inst_type); + AddArrayMetadata(inst_type); ArrayMetadata t_data = array_metadata[inst_type]; - if (! t_data.IsArray && ! t_data.IsList) - throw new JsonException (String.Format ( + if (!t_data.IsArray && !t_data.IsList) + throw new JsonException(String.Format( "Type {0} can't act as an array", inst_type)); IList list; Type elem_type; - if (! t_data.IsArray) { - list = (IList) Activator.CreateInstance (inst_type); + if (!t_data.IsArray) + { + list = (IList)Activator.CreateInstance(inst_type); elem_type = t_data.ElementType; - } else { - list = new ArrayList (); - elem_type = inst_type.GetElementType (); + } + else + { + list = new ArrayList(); + elem_type = inst_type.GetElementType(); } list.Clear(); - while (true) { - object item = ReadValue (elem_type, reader); + while (true) + { + object item = ReadValue(elem_type, reader); if (item == null && reader.Token == JsonToken.ArrayEnd) break; - list.Add (item); + list.Add(item); } - if (t_data.IsArray) { + if (t_data.IsArray) + { int n = list.Count; - instance = Array.CreateInstance (elem_type, n); + instance = Array.CreateInstance(elem_type, n); for (int i = 0; i < n; i++) - ((Array) instance).SetValue (list[i], i); - } else + ((Array)instance).SetValue(list[i], i); + } + else instance = list; - } else if (reader.Token == JsonToken.ObjectStart) { - AddObjectMetadata (value_type); + } + else if (reader.Token == JsonToken.ObjectStart) + { + AddObjectMetadata(value_type); ObjectMetadata t_data = object_metadata[value_type]; - instance = Activator.CreateInstance (value_type); + instance = Activator.CreateInstance(value_type); - while (true) { - reader.Read (); + while (true) + { + reader.Read(); if (reader.Token == JsonToken.ObjectEnd) break; - string property = (string) reader.Value; + string property = (string)reader.Value; - if (t_data.Properties.ContainsKey (property)) { + if (t_data.Properties.ContainsKey(property)) + { PropertyMetadata prop_data = t_data.Properties[property]; - if (prop_data.IsField) { - ((FieldInfo) prop_data.Info).SetValue ( - instance, ReadValue (prop_data.Type, reader)); - } else { + if (prop_data.IsField) + { + ((FieldInfo)prop_data.Info).SetValue( + instance, ReadValue(prop_data.Type, reader)); + } + else + { PropertyInfo p_info = - (PropertyInfo) prop_data.Info; + (PropertyInfo)prop_data.Info; if (p_info.CanWrite) - p_info.SetValue ( + p_info.SetValue( instance, - ReadValue (prop_data.Type, reader), + ReadValue(prop_data.Type, reader), null); else - ReadValue (prop_data.Type, reader); + ReadValue(prop_data.Type, reader); } - } else { - if (! t_data.IsDictionary) { - - if (! reader.SkipNonMembers) { - throw new JsonException (String.Format ( + } + else + { + if (!t_data.IsDictionary) + { + + if (!reader.SkipNonMembers) + { + throw new JsonException(String.Format( "The type {0} doesn't have the " + "property '{1}'", inst_type, property)); - } else { - ReadSkip (reader); + } + else + { + ReadSkip(reader); continue; } } - ((IDictionary) instance).Add ( - property, ReadValue ( + ((IDictionary)instance).Add( + property, ReadValue( t_data.ElementType, reader)); } @@ -485,65 +536,74 @@ private static object ReadValue (Type inst_type, JsonReader reader) return instance; } - private static IJsonWrapper ReadValue (WrapperFactory factory, + private static IJsonWrapper ReadValue(WrapperFactory factory, JsonReader reader) { - reader.Read (); + reader.Read(); if (reader.Token == JsonToken.ArrayEnd || reader.Token == JsonToken.Null) return null; - IJsonWrapper instance = factory (); + IJsonWrapper instance = factory(); - if (reader.Token == JsonToken.String) { - instance.SetString ((string) reader.Value); + if (reader.Token == JsonToken.String) + { + instance.SetString((string)reader.Value); return instance; } - if (reader.Token == JsonToken.Double) { - instance.SetDouble ((double) reader.Value); + if (reader.Token == JsonToken.Double) + { + instance.SetDouble((double)reader.Value); return instance; } - if (reader.Token == JsonToken.Int) { - instance.SetInt ((int) reader.Value); + if (reader.Token == JsonToken.Int) + { + instance.SetInt((int)reader.Value); return instance; } - if (reader.Token == JsonToken.Long) { - instance.SetLong ((long) reader.Value); + if (reader.Token == JsonToken.Long) + { + instance.SetLong((long)reader.Value); return instance; } - if (reader.Token == JsonToken.Boolean) { - instance.SetBoolean ((bool) reader.Value); + if (reader.Token == JsonToken.Boolean) + { + instance.SetBoolean((bool)reader.Value); return instance; } - if (reader.Token == JsonToken.ArrayStart) { - instance.SetJsonType (JsonType.Array); + if (reader.Token == JsonToken.ArrayStart) + { + instance.SetJsonType(JsonType.Array); - while (true) { - IJsonWrapper item = ReadValue (factory, reader); + while (true) + { + IJsonWrapper item = ReadValue(factory, reader); if (item == null && reader.Token == JsonToken.ArrayEnd) break; - ((IList) instance).Add (item); + ((IList)instance).Add(item); } } - else if (reader.Token == JsonToken.ObjectStart) { - instance.SetJsonType (JsonType.Object); + else if (reader.Token == JsonToken.ObjectStart) + { + instance.SetJsonType(JsonType.Object); - while (true) { - reader.Read (); + while (true) + { + reader.Read(); if (reader.Token == JsonToken.ObjectEnd) break; - string property = (string) reader.Value; + string property = (string)reader.Value; - ((IDictionary) instance)[property] = ReadValue ( + ((IDictionary)instance)[property] = ReadValue( factory, reader); } @@ -552,202 +612,235 @@ private static IJsonWrapper ReadValue (WrapperFactory factory, return instance; } - private static void ReadSkip (JsonReader reader) + private static void ReadSkip(JsonReader reader) { - ToWrapper ( - delegate { return new JsonMockWrapper (); }, reader); + ToWrapper( + delegate { return new JsonMockWrapper(); }, reader); } - private static void RegisterBaseExporters () + private static void RegisterBaseExporters() { - base_exporters_table[typeof (byte)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToInt32 ((byte) obj)); + // This method is only called from the static initializer, + // so there is no need to explicitly lock any static members here + base_exporters_table[typeof(byte)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToInt32((byte)obj)); }; - base_exporters_table[typeof (char)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToString ((char) obj)); + base_exporters_table[typeof(char)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToString((char)obj)); }; - base_exporters_table[typeof (DateTime)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToString ((DateTime) obj, + base_exporters_table[typeof(DateTime)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToString((DateTime)obj, datetime_format)); }; - base_exporters_table[typeof (decimal)] = - delegate (object obj, JsonWriter writer) { - writer.Write ((decimal) obj); + base_exporters_table[typeof(decimal)] = + delegate (object obj, JsonWriter writer) + { + writer.Write((decimal)obj); }; - base_exporters_table[typeof (sbyte)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToInt32 ((sbyte) obj)); + base_exporters_table[typeof(sbyte)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToInt32((sbyte)obj)); }; - base_exporters_table[typeof (short)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToInt32 ((short) obj)); + base_exporters_table[typeof(short)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToInt32((short)obj)); }; - base_exporters_table[typeof (ushort)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToInt32 ((ushort) obj)); + base_exporters_table[typeof(ushort)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToInt32((ushort)obj)); }; - base_exporters_table[typeof (uint)] = - delegate (object obj, JsonWriter writer) { - writer.Write (Convert.ToUInt64 ((uint) obj)); + base_exporters_table[typeof(uint)] = + delegate (object obj, JsonWriter writer) + { + writer.Write(Convert.ToUInt64((uint)obj)); }; - base_exporters_table[typeof (ulong)] = - delegate (object obj, JsonWriter writer) { - writer.Write ((ulong) obj); + base_exporters_table[typeof(ulong)] = + delegate (object obj, JsonWriter writer) + { + writer.Write((ulong)obj); }; base_exporters_table[typeof(DateTimeOffset)] = - delegate (object obj, JsonWriter writer) { + delegate (object obj, JsonWriter writer) + { writer.Write(((DateTimeOffset)obj).ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz", datetime_format)); }; } - private static void RegisterBaseImporters () + private static void RegisterBaseImporters() { ImporterFunc importer; - importer = delegate (object input) { - return Convert.ToByte ((int) input); + // This method is only called from the static initializer, + // so there is no need to explicitly lock any static members here + importer = delegate (object input) + { + return Convert.ToByte((int)input); }; - RegisterImporter (base_importers_table, typeof (int), - typeof (byte), importer); + RegisterImporter(base_importers_table, typeof(int), + typeof(byte), importer); - importer = delegate (object input) { - return Convert.ToUInt64 ((int) input); + importer = delegate (object input) + { + return Convert.ToUInt64((int)input); }; - RegisterImporter (base_importers_table, typeof (int), - typeof (ulong), importer); + RegisterImporter(base_importers_table, typeof(int), + typeof(ulong), importer); - importer = delegate (object input) { + importer = delegate (object input) + { return Convert.ToInt64((int)input); }; RegisterImporter(base_importers_table, typeof(int), typeof(long), importer); - importer = delegate (object input) { - return Convert.ToSByte ((int) input); + importer = delegate (object input) + { + return Convert.ToSByte((int)input); }; - RegisterImporter (base_importers_table, typeof (int), - typeof (sbyte), importer); + RegisterImporter(base_importers_table, typeof(int), + typeof(sbyte), importer); - importer = delegate (object input) { - return Convert.ToInt16 ((int) input); + importer = delegate (object input) + { + return Convert.ToInt16((int)input); }; - RegisterImporter (base_importers_table, typeof (int), - typeof (short), importer); + RegisterImporter(base_importers_table, typeof(int), + typeof(short), importer); - importer = delegate (object input) { - return Convert.ToUInt16 ((int) input); + importer = delegate (object input) + { + return Convert.ToUInt16((int)input); }; - RegisterImporter (base_importers_table, typeof (int), - typeof (ushort), importer); + RegisterImporter(base_importers_table, typeof(int), + typeof(ushort), importer); - importer = delegate (object input) { - return Convert.ToUInt32 ((int) input); + importer = delegate (object input) + { + return Convert.ToUInt32((int)input); }; - RegisterImporter (base_importers_table, typeof (int), - typeof (uint), importer); + RegisterImporter(base_importers_table, typeof(int), + typeof(uint), importer); - importer = delegate (object input) { - return Convert.ToSingle ((int) input); + importer = delegate (object input) + { + return Convert.ToSingle((int)input); }; - RegisterImporter (base_importers_table, typeof (int), - typeof (float), importer); + RegisterImporter(base_importers_table, typeof(int), + typeof(float), importer); - importer = delegate (object input) { - return Convert.ToDouble ((int) input); + importer = delegate (object input) + { + return Convert.ToDouble((int)input); }; - RegisterImporter (base_importers_table, typeof (int), - typeof (double), importer); + RegisterImporter(base_importers_table, typeof(int), + typeof(double), importer); - importer = delegate (object input) { - return Convert.ToDecimal ((double) input); + importer = delegate (object input) + { + return Convert.ToDecimal((double)input); }; - RegisterImporter (base_importers_table, typeof (double), - typeof (decimal), importer); + RegisterImporter(base_importers_table, typeof(double), + typeof(decimal), importer); - importer = delegate (object input) { + importer = delegate (object input) + { return Convert.ToSingle((double)input); }; RegisterImporter(base_importers_table, typeof(double), typeof(float), importer); - importer = delegate (object input) { - return Convert.ToUInt32 ((long) input); + importer = delegate (object input) + { + return Convert.ToUInt32((long)input); }; - RegisterImporter (base_importers_table, typeof (long), - typeof (uint), importer); + RegisterImporter(base_importers_table, typeof(long), + typeof(uint), importer); - importer = delegate (object input) { - return Convert.ToChar ((string) input); + importer = delegate (object input) + { + return Convert.ToChar((string)input); }; - RegisterImporter (base_importers_table, typeof (string), - typeof (char), importer); + RegisterImporter(base_importers_table, typeof(string), + typeof(char), importer); - importer = delegate (object input) { - return Convert.ToDateTime ((string) input, datetime_format); + importer = delegate (object input) + { + return Convert.ToDateTime((string)input, datetime_format); }; - RegisterImporter (base_importers_table, typeof (string), - typeof (DateTime), importer); + RegisterImporter(base_importers_table, typeof(string), + typeof(DateTime), importer); - importer = delegate (object input) { + importer = delegate (object input) + { return DateTimeOffset.Parse((string)input, datetime_format); }; RegisterImporter(base_importers_table, typeof(string), typeof(DateTimeOffset), importer); } - private static void RegisterImporter ( + private static void RegisterImporter( IDictionary> table, Type json_type, Type value_type, ImporterFunc importer) { - if (! table.ContainsKey (json_type)) - table.Add (json_type, new Dictionary ()); + if (!table.ContainsKey(json_type)) + table.Add(json_type, new Dictionary()); table[json_type][value_type] = importer; } - private static void WriteValue (object obj, JsonWriter writer, + private static void WriteValue(object obj, JsonWriter writer, bool writer_is_private, int depth) { if (depth > max_nesting_depth) - throw new JsonException ( - String.Format ("Max allowed object depth reached while " + + throw new JsonException( + String.Format("Max allowed object depth reached while " + "trying to export from type {0}", - obj.GetType ())); + obj.GetType())); - if (obj == null) { - writer.Write (null); + if (obj == null) + { + writer.Write(null); return; } - if (obj is IJsonWrapper) { + if (obj is IJsonWrapper) + { if (writer_is_private) - writer.TextWriter.Write (((IJsonWrapper) obj).ToJson ()); + writer.TextWriter.Write(((IJsonWrapper)obj).ToJson()); else - ((IJsonWrapper) obj).ToJson (writer); + ((IJsonWrapper)obj).ToJson(writer); return; } - if (obj is String) { - writer.Write ((string) obj); + if (obj is String) + { + writer.Write((string)obj); return; } - if (obj is Double) { - writer.Write ((double) obj); + if (obj is Double) + { + writer.Write((double)obj); return; } @@ -757,231 +850,261 @@ private static void WriteValue (object obj, JsonWriter writer, return; } - if (obj is Int32) { - writer.Write ((int) obj); + if (obj is Int32) + { + writer.Write((int)obj); return; } - if (obj is Boolean) { - writer.Write ((bool) obj); + if (obj is Boolean) + { + writer.Write((bool)obj); return; } - if (obj is Int64) { - writer.Write ((long) obj); + if (obj is Int64) + { + writer.Write((long)obj); return; } - if (obj is Array) { - writer.WriteArrayStart (); + if (obj is Array) + { + writer.WriteArrayStart(); - foreach (object elem in (Array) obj) - WriteValue (elem, writer, writer_is_private, depth + 1); + foreach (object elem in (Array)obj) + WriteValue(elem, writer, writer_is_private, depth + 1); - writer.WriteArrayEnd (); + writer.WriteArrayEnd(); return; } - if (obj is IList) { - writer.WriteArrayStart (); - foreach (object elem in (IList) obj) - WriteValue (elem, writer, writer_is_private, depth + 1); - writer.WriteArrayEnd (); + if (obj is IList) + { + writer.WriteArrayStart(); + foreach (object elem in (IList)obj) + WriteValue(elem, writer, writer_is_private, depth + 1); + writer.WriteArrayEnd(); return; } - if (obj is IDictionary dictionary) { - writer.WriteObjectStart (); - foreach (DictionaryEntry entry in dictionary) { + if (obj is IDictionary dictionary) + { + writer.WriteObjectStart(); + foreach (DictionaryEntry entry in dictionary) + { var propertyName = entry.Key is string key ? key : Convert.ToString(entry.Key, CultureInfo.InvariantCulture); - writer.WritePropertyName (propertyName); - WriteValue (entry.Value, writer, writer_is_private, + writer.WritePropertyName(propertyName); + WriteValue(entry.Value, writer, writer_is_private, depth + 1); } - writer.WriteObjectEnd (); + writer.WriteObjectEnd(); return; } - Type obj_type = obj.GetType (); + Type obj_type = obj.GetType(); // See if there's a custom exporter for the object - if (custom_exporters_table.ContainsKey (obj_type)) { - ExporterFunc exporter = custom_exporters_table[obj_type]; - exporter (obj, writer); + lock (custom_exporters_table_lock) + { + if (custom_exporters_table.TryGetValue(obj_type, out ExporterFunc customExporter)) + { + customExporter(obj, writer); - return; + return; + } } // If not, maybe there's a base exporter - if (base_exporters_table.ContainsKey (obj_type)) { - ExporterFunc exporter = base_exporters_table[obj_type]; - exporter (obj, writer); + if (base_exporters_table.TryGetValue(obj_type, out ExporterFunc baseExporter)) + { + baseExporter(obj, writer); return; } // Last option, let's see if it's an enum - if (obj is Enum) { - Type e_type = Enum.GetUnderlyingType (obj_type); - - if (e_type == typeof (long)) - writer.Write ((long) obj); - else if (e_type == typeof (uint)) - writer.Write ((uint) obj); - else if (e_type == typeof (ulong)) - writer.Write ((ulong) obj); + if (obj is Enum) + { + Type e_type = Enum.GetUnderlyingType(obj_type); + + if (e_type == typeof(long)) + writer.Write((long)obj); + else if (e_type == typeof(uint)) + writer.Write((uint)obj); + else if (e_type == typeof(ulong)) + writer.Write((ulong)obj); else if (e_type == typeof(ushort)) - writer.Write ((ushort)obj); + writer.Write((ushort)obj); else if (e_type == typeof(short)) - writer.Write ((short)obj); + writer.Write((short)obj); else if (e_type == typeof(byte)) - writer.Write ((byte)obj); + writer.Write((byte)obj); else if (e_type == typeof(sbyte)) - writer.Write ((sbyte)obj); + writer.Write((sbyte)obj); else - writer.Write ((int) obj); + writer.Write((int)obj); return; } // Okay, so it looks like the input should be exported as an // object - AddTypeProperties (obj_type); + AddTypeProperties(obj_type); IList props = type_properties[obj_type]; - writer.WriteObjectStart (); - foreach (PropertyMetadata p_data in props) { - if (p_data.IsField) { - writer.WritePropertyName (p_data.Info.Name); - WriteValue (((FieldInfo) p_data.Info).GetValue (obj), + writer.WriteObjectStart(); + foreach (PropertyMetadata p_data in props) + { + if (p_data.IsField) + { + writer.WritePropertyName(p_data.Info.Name); + WriteValue(((FieldInfo)p_data.Info).GetValue(obj), writer, writer_is_private, depth + 1); } - else { - PropertyInfo p_info = (PropertyInfo) p_data.Info; + else + { + PropertyInfo p_info = (PropertyInfo)p_data.Info; - if (p_info.CanRead) { - writer.WritePropertyName (p_data.Info.Name); - WriteValue (p_info.GetValue (obj, null), + if (p_info.CanRead) + { + writer.WritePropertyName(p_data.Info.Name); + WriteValue(p_info.GetValue(obj, null), writer, writer_is_private, depth + 1); } } } - writer.WriteObjectEnd (); + writer.WriteObjectEnd(); } #endregion - public static string ToJson (object obj) + public static string ToJson(object obj) { - lock (static_writer_lock) { - static_writer.Reset (); + lock (static_writer_lock) + { + static_writer.Reset(); - WriteValue (obj, static_writer, true, 0); + WriteValue(obj, static_writer, true, 0); - return static_writer.ToString (); + return static_writer.ToString(); } } - public static void ToJson (object obj, JsonWriter writer) + public static void ToJson(object obj, JsonWriter writer) { - WriteValue (obj, writer, false, 0); + WriteValue(obj, writer, false, 0); } - public static JsonData ToObject (JsonReader reader) + public static JsonData ToObject(JsonReader reader) { - return (JsonData) ToWrapper ( - delegate { return new JsonData (); }, reader); + return (JsonData)ToWrapper( + delegate { return new JsonData(); }, reader); } - public static JsonData ToObject (TextReader reader) + public static JsonData ToObject(TextReader reader) { - JsonReader json_reader = new JsonReader (reader); + JsonReader json_reader = new JsonReader(reader); - return (JsonData) ToWrapper ( - delegate { return new JsonData (); }, json_reader); + return (JsonData)ToWrapper( + delegate { return new JsonData(); }, json_reader); } - public static JsonData ToObject (string json) + public static JsonData ToObject(string json) { - return (JsonData) ToWrapper ( - delegate { return new JsonData (); }, json); + return (JsonData)ToWrapper( + delegate { return new JsonData(); }, json); } - public static T ToObject (JsonReader reader) + public static T ToObject(JsonReader reader) { - return (T) ReadValue (typeof (T), reader); + return (T)ReadValue(typeof(T), reader); } - public static T ToObject (TextReader reader) + public static T ToObject(TextReader reader) { - JsonReader json_reader = new JsonReader (reader); + JsonReader json_reader = new JsonReader(reader); - return (T) ReadValue (typeof (T), json_reader); + return (T)ReadValue(typeof(T), json_reader); } - public static T ToObject (string json) + public static T ToObject(string json) { - JsonReader reader = new JsonReader (json); + JsonReader reader = new JsonReader(json); - return (T) ReadValue (typeof (T), reader); + return (T)ReadValue(typeof(T), reader); } - public static object ToObject(string json, Type ConvertType ) + public static object ToObject(string json, Type ConvertType) { JsonReader reader = new JsonReader(json); return ReadValue(ConvertType, reader); } - public static IJsonWrapper ToWrapper (WrapperFactory factory, + public static IJsonWrapper ToWrapper(WrapperFactory factory, JsonReader reader) { - return ReadValue (factory, reader); + return ReadValue(factory, reader); } - public static IJsonWrapper ToWrapper (WrapperFactory factory, + public static IJsonWrapper ToWrapper(WrapperFactory factory, string json) { - JsonReader reader = new JsonReader (json); + JsonReader reader = new JsonReader(json); - return ReadValue (factory, reader); + return ReadValue(factory, reader); } - public static void RegisterExporter (ExporterFunc exporter) + public static void RegisterExporter(ExporterFunc exporter) { ExporterFunc exporter_wrapper = - delegate (object obj, JsonWriter writer) { - exporter ((T) obj, writer); + delegate (object obj, JsonWriter writer) + { + exporter((T)obj, writer); }; - custom_exporters_table[typeof (T)] = exporter_wrapper; + lock (custom_exporters_table_lock) + { + custom_exporters_table[typeof(T)] = exporter_wrapper; + } } - public static void RegisterImporter ( + public static void RegisterImporter( ImporterFunc importer) { ImporterFunc importer_wrapper = - delegate (object input) { - return importer ((TJson) input); + delegate (object input) + { + return importer((TJson)input); }; - RegisterImporter (custom_importers_table, typeof (TJson), - typeof (TValue), importer_wrapper); + lock (custom_importers_table_lock) + { + RegisterImporter(custom_importers_table, typeof(TJson), + typeof(TValue), importer_wrapper); + } } - public static void UnregisterExporters () + public static void UnregisterExporters() { - custom_exporters_table.Clear (); + lock (custom_exporters_table_lock) + { + custom_exporters_table.Clear(); + } } - public static void UnregisterImporters () + public static void UnregisterImporters() { - custom_importers_table.Clear (); + lock (custom_importers_table_lock) + { + custom_importers_table.Clear(); + } } } } From 56995a48187b9800cc71cb3b748a9156f2b2e2db Mon Sep 17 00:00:00 2001 From: DaveBlack Date: Tue, 29 Aug 2023 15:49:59 -0500 Subject: [PATCH 2/4] - fix issue 142 (race conditions on static dictionaries) --- src/LitJson/JsonMapper.cs | 891 +++++++++++++++++--------------------- 1 file changed, 404 insertions(+), 487 deletions(-) diff --git a/src/LitJson/JsonMapper.cs b/src/LitJson/JsonMapper.cs index f2d7f2b..b4a447c 100644 --- a/src/LitJson/JsonMapper.cs +++ b/src/LitJson/JsonMapper.cs @@ -22,8 +22,8 @@ namespace LitJson internal struct PropertyMetadata { public MemberInfo Info; - public bool IsField; - public Type Type; + public bool IsField; + public Type Type; } @@ -34,12 +34,10 @@ internal struct ArrayMetadata private bool is_list; - public Type ElementType - { - get - { + public Type ElementType { + get { if (element_type == null) - return typeof(JsonData); + return typeof (JsonData); return element_type; } @@ -47,14 +45,12 @@ public Type ElementType set { element_type = value; } } - public bool IsArray - { + public bool IsArray { get { return is_array; } set { is_array = value; } } - public bool IsList - { + public bool IsList { get { return is_list; } set { is_list = value; } } @@ -69,12 +65,10 @@ internal struct ObjectMetadata private IDictionary properties; - public Type ElementType - { - get - { + public Type ElementType { + get { if (element_type == null) - return typeof(JsonData); + return typeof (JsonData); return element_type; } @@ -82,27 +76,25 @@ public Type ElementType set { element_type = value; } } - public bool IsDictionary - { + public bool IsDictionary { get { return is_dictionary; } set { is_dictionary = value; } } - public IDictionary Properties - { + public IDictionary Properties { get { return properties; } set { properties = value; } } } - internal delegate void ExporterFunc(object obj, JsonWriter writer); - public delegate void ExporterFunc(T obj, JsonWriter writer); + internal delegate void ExporterFunc (object obj, JsonWriter writer); + public delegate void ExporterFunc (T obj, JsonWriter writer); - internal delegate object ImporterFunc(object input); - public delegate TValue ImporterFunc(TJson input); + internal delegate object ImporterFunc (object input); + public delegate TValue ImporterFunc (TJson input); - public delegate IJsonWrapper WrapperFactory(); + public delegate IJsonWrapper WrapperFactory (); public class JsonMapper @@ -123,212 +115,189 @@ public class JsonMapper private static readonly object custom_importers_table_lock = new Object(); private static readonly IDictionary array_metadata; - private static readonly object array_metadata_lock = new Object(); + private static readonly object array_metadata_lock = new Object (); private static readonly IDictionary> conv_ops; - private static readonly object conv_ops_lock = new Object(); + private static readonly object conv_ops_lock = new Object (); private static readonly IDictionary object_metadata; - private static readonly object object_metadata_lock = new Object(); + private static readonly object object_metadata_lock = new Object (); private static readonly IDictionary> type_properties; - private static readonly object type_properties_lock = new Object(); + private static readonly object type_properties_lock = new Object (); - private static readonly JsonWriter static_writer; - private static readonly object static_writer_lock = new Object(); + private static readonly JsonWriter static_writer; + private static readonly object static_writer_lock = new Object (); #endregion #region Constructors - static JsonMapper() + static JsonMapper () { max_nesting_depth = 100; - array_metadata = new Dictionary(); - conv_ops = new Dictionary>(); - object_metadata = new Dictionary(); + array_metadata = new Dictionary (); + conv_ops = new Dictionary> (); + object_metadata = new Dictionary (); type_properties = new Dictionary>(); + IList> (); - static_writer = new JsonWriter(); + static_writer = new JsonWriter (); datetime_format = DateTimeFormatInfo.InvariantInfo; - base_exporters_table = new Dictionary(); - custom_exporters_table = new Dictionary(); + base_exporters_table = new Dictionary (); + custom_exporters_table = new Dictionary (); base_importers_table = new Dictionary>(); + IDictionary> (); custom_importers_table = new Dictionary>(); + IDictionary> (); - RegisterBaseExporters(); - RegisterBaseImporters(); + RegisterBaseExporters (); + RegisterBaseImporters (); } #endregion #region Private Methods - private static void AddArrayMetadata(Type type) + private static void AddArrayMetadata (Type type) { - if (array_metadata.ContainsKey(type)) + if (array_metadata.ContainsKey (type)) return; - ArrayMetadata data = new ArrayMetadata(); + ArrayMetadata data = new ArrayMetadata (); data.IsArray = type.IsArray; - if (type.GetInterface("System.Collections.IList") != null) + if (type.GetInterface ("System.Collections.IList") != null) data.IsList = true; - foreach (PropertyInfo p_info in type.GetProperties()) - { + foreach (PropertyInfo p_info in type.GetProperties ()) { if (p_info.Name != "Item") continue; - ParameterInfo[] parameters = p_info.GetIndexParameters(); + ParameterInfo[] parameters = p_info.GetIndexParameters (); if (parameters.Length != 1) continue; - if (parameters[0].ParameterType == typeof(int)) + if (parameters[0].ParameterType == typeof (int)) data.ElementType = p_info.PropertyType; } - lock (array_metadata_lock) - { - try - { - array_metadata.Add(type, data); - } - catch (ArgumentException) - { + lock (array_metadata_lock) { + try { + array_metadata.Add (type, data); + } catch (ArgumentException) { return; } } } - private static void AddObjectMetadata(Type type) + private static void AddObjectMetadata (Type type) { - if (object_metadata.ContainsKey(type)) + if (object_metadata.ContainsKey (type)) return; - ObjectMetadata data = new ObjectMetadata(); + ObjectMetadata data = new ObjectMetadata (); - if (type.GetInterface("System.Collections.IDictionary") != null) + if (type.GetInterface ("System.Collections.IDictionary") != null) data.IsDictionary = true; - data.Properties = new Dictionary(); + data.Properties = new Dictionary (); - foreach (PropertyInfo p_info in type.GetProperties()) - { - if (p_info.Name == "Item") - { - ParameterInfo[] parameters = p_info.GetIndexParameters(); + foreach (PropertyInfo p_info in type.GetProperties ()) { + if (p_info.Name == "Item") { + ParameterInfo[] parameters = p_info.GetIndexParameters (); if (parameters.Length != 1) continue; - if (parameters[0].ParameterType == typeof(string)) + if (parameters[0].ParameterType == typeof (string)) data.ElementType = p_info.PropertyType; continue; } - PropertyMetadata p_data = new PropertyMetadata(); + PropertyMetadata p_data = new PropertyMetadata (); p_data.Info = p_info; p_data.Type = p_info.PropertyType; - data.Properties.Add(p_info.Name, p_data); + data.Properties.Add (p_info.Name, p_data); } - foreach (FieldInfo f_info in type.GetFields()) - { - PropertyMetadata p_data = new PropertyMetadata(); + foreach (FieldInfo f_info in type.GetFields ()) { + PropertyMetadata p_data = new PropertyMetadata (); p_data.Info = f_info; p_data.IsField = true; p_data.Type = f_info.FieldType; - data.Properties.Add(f_info.Name, p_data); + data.Properties.Add (f_info.Name, p_data); } - lock (object_metadata_lock) - { - try - { - object_metadata.Add(type, data); - } - catch (ArgumentException) - { + lock (object_metadata_lock) { + try { + object_metadata.Add (type, data); + } catch (ArgumentException) { return; } } } - private static void AddTypeProperties(Type type) + private static void AddTypeProperties (Type type) { - if (type_properties.ContainsKey(type)) + if (type_properties.ContainsKey (type)) return; - IList props = new List(); + IList props = new List (); - foreach (PropertyInfo p_info in type.GetProperties()) - { + foreach (PropertyInfo p_info in type.GetProperties ()) { if (p_info.Name == "Item") continue; - PropertyMetadata p_data = new PropertyMetadata(); + PropertyMetadata p_data = new PropertyMetadata (); p_data.Info = p_info; p_data.IsField = false; - props.Add(p_data); + props.Add (p_data); } - foreach (FieldInfo f_info in type.GetFields()) - { - PropertyMetadata p_data = new PropertyMetadata(); + foreach (FieldInfo f_info in type.GetFields ()) { + PropertyMetadata p_data = new PropertyMetadata (); p_data.Info = f_info; p_data.IsField = true; - props.Add(p_data); + props.Add (p_data); } - lock (type_properties_lock) - { - try - { - type_properties.Add(type, props); - } - catch (ArgumentException) - { + lock (type_properties_lock) { + try { + type_properties.Add (type, props); + } catch (ArgumentException) { return; } } } - private static MethodInfo GetConvOp(Type t1, Type t2) + private static MethodInfo GetConvOp (Type t1, Type t2) { - lock (conv_ops_lock) - { - if (!conv_ops.ContainsKey(t1)) - conv_ops.Add(t1, new Dictionary()); + lock (conv_ops_lock) { + if (! conv_ops.ContainsKey (t1)) + conv_ops.Add (t1, new Dictionary ()); } - if (conv_ops[t1].ContainsKey(t2)) + if (conv_ops[t1].ContainsKey (t2)) return conv_ops[t1][t2]; - MethodInfo op = t1.GetMethod( + MethodInfo op = t1.GetMethod ( "op_Implicit", new Type[] { t2 }); - lock (conv_ops_lock) - { - try - { - conv_ops[t1].Add(t2, op); - } - catch (ArgumentException) - { + lock (conv_ops_lock) { + try { + conv_ops[t1].Add (t2, op); + } catch (ArgumentException) { return conv_ops[t1][t2]; } } @@ -336,9 +305,9 @@ private static MethodInfo GetConvOp(Type t1, Type t2) return op; } - private static object ReadValue(Type inst_type, JsonReader reader) + private static object ReadValue (Type inst_type, JsonReader reader) { - reader.Read(); + reader.Read (); if (reader.Token == JsonToken.ArrayEnd) return null; @@ -346,20 +315,18 @@ private static object ReadValue(Type inst_type, JsonReader reader) Type underlying_type = Nullable.GetUnderlyingType(inst_type); Type value_type = underlying_type ?? inst_type; - if (reader.Token == JsonToken.Null) - { -#if NETSTANDARD1_5 + if (reader.Token == JsonToken.Null) { + #if NETSTANDARD1_5 if (inst_type.IsClass() || underlying_type != null) { return null; } -#else - if (inst_type.IsClass || underlying_type != null) - { + #else + if (inst_type.IsClass || underlying_type != null) { return null; } -#endif + #endif - throw new JsonException(String.Format( + throw new JsonException (String.Format ( "Can't assign null to an instance of type {0}", inst_type)); } @@ -368,28 +335,44 @@ private static object ReadValue(Type inst_type, JsonReader reader) reader.Token == JsonToken.Int || reader.Token == JsonToken.Long || reader.Token == JsonToken.String || - reader.Token == JsonToken.Boolean) - { + reader.Token == JsonToken.Boolean) { - Type json_type = reader.Value.GetType(); + Type json_type = reader.Value.GetType (); - if (value_type.IsAssignableFrom(json_type)) + if (value_type.IsAssignableFrom (json_type)) return reader.Value; // If there's a custom importer that fits, use it - lock (custom_importers_table_lock) - { + lock (custom_importers_table_lock) { + //if (custom_importers_table.ContainsKey (json_type) && + // custom_importers_table[json_type].ContainsKey ( + // value_type)) { + + // ImporterFunc importer = + // custom_importers_table[json_type][value_type]; + + // return importer (reader.Value); + //} if (custom_importers_table.TryGetValue(json_type, out IDictionary customImporterTablesValue) && - customImporterTablesValue.TryGetValue(value_type, out ImporterFunc customImporter)) - { + customImporterTablesValue.TryGetValue(value_type, out ImporterFunc customImporter)) { + return customImporter(reader.Value); } } // Maybe there's a base importer that works + //if (base_importers_table.ContainsKey (json_type) && + // base_importers_table[json_type].ContainsKey ( + // value_type)) { + + // ImporterFunc importer = + // base_importers_table[json_type][value_type]; + + // return importer (reader.Value); + //} if (base_importers_table.TryGetValue(json_type, out IDictionary baseImporterTablesValue) && - baseImporterTablesValue.TryGetValue(value_type, out ImporterFunc baseImporter)) - { + baseImporterTablesValue.TryGetValue(value_type, out ImporterFunc baseImporter)) { + return baseImporter(reader.Value); } @@ -399,133 +382,113 @@ private static object ReadValue(Type inst_type, JsonReader reader) return Enum.ToObject (value_type, reader.Value); #else if (value_type.IsEnum) - return Enum.ToObject(value_type, reader.Value); -#endif + return Enum.ToObject (value_type, reader.Value); + #endif // Try using an implicit conversion operator - MethodInfo conv_op = GetConvOp(value_type, json_type); + MethodInfo conv_op = GetConvOp (value_type, json_type); if (conv_op != null) - return conv_op.Invoke(null, + return conv_op.Invoke (null, new object[] { reader.Value }); // No luck - throw new JsonException(String.Format( + throw new JsonException (String.Format ( "Can't assign value '{0}' (type {1}) to type {2}", reader.Value, json_type, inst_type)); } object instance = null; - if (reader.Token == JsonToken.ArrayStart) - { + if (reader.Token == JsonToken.ArrayStart) { - AddArrayMetadata(inst_type); + AddArrayMetadata (inst_type); ArrayMetadata t_data = array_metadata[inst_type]; - if (!t_data.IsArray && !t_data.IsList) - throw new JsonException(String.Format( + if (! t_data.IsArray && ! t_data.IsList) + throw new JsonException (String.Format ( "Type {0} can't act as an array", inst_type)); IList list; Type elem_type; - if (!t_data.IsArray) - { - list = (IList)Activator.CreateInstance(inst_type); + if (! t_data.IsArray) { + list = (IList) Activator.CreateInstance (inst_type); elem_type = t_data.ElementType; - } - else - { - list = new ArrayList(); - elem_type = inst_type.GetElementType(); + } else { + list = new ArrayList (); + elem_type = inst_type.GetElementType (); } list.Clear(); - while (true) - { - object item = ReadValue(elem_type, reader); + while (true) { + object item = ReadValue (elem_type, reader); if (item == null && reader.Token == JsonToken.ArrayEnd) break; - list.Add(item); + list.Add (item); } - if (t_data.IsArray) - { + if (t_data.IsArray) { int n = list.Count; - instance = Array.CreateInstance(elem_type, n); + instance = Array.CreateInstance (elem_type, n); for (int i = 0; i < n; i++) - ((Array)instance).SetValue(list[i], i); - } - else + ((Array) instance).SetValue (list[i], i); + } else instance = list; - } - else if (reader.Token == JsonToken.ObjectStart) - { - AddObjectMetadata(value_type); + } else if (reader.Token == JsonToken.ObjectStart) { + AddObjectMetadata (value_type); ObjectMetadata t_data = object_metadata[value_type]; - instance = Activator.CreateInstance(value_type); + instance = Activator.CreateInstance (value_type); - while (true) - { - reader.Read(); + while (true) { + reader.Read (); if (reader.Token == JsonToken.ObjectEnd) break; - string property = (string)reader.Value; + string property = (string) reader.Value; - if (t_data.Properties.ContainsKey(property)) - { + if (t_data.Properties.ContainsKey (property)) { PropertyMetadata prop_data = t_data.Properties[property]; - if (prop_data.IsField) - { - ((FieldInfo)prop_data.Info).SetValue( - instance, ReadValue(prop_data.Type, reader)); - } - else - { + if (prop_data.IsField) { + ((FieldInfo) prop_data.Info).SetValue ( + instance, ReadValue (prop_data.Type, reader)); + } else { PropertyInfo p_info = - (PropertyInfo)prop_data.Info; + (PropertyInfo) prop_data.Info; if (p_info.CanWrite) - p_info.SetValue( + p_info.SetValue ( instance, - ReadValue(prop_data.Type, reader), + ReadValue (prop_data.Type, reader), null); else - ReadValue(prop_data.Type, reader); + ReadValue (prop_data.Type, reader); } - } - else - { - if (!t_data.IsDictionary) - { - - if (!reader.SkipNonMembers) - { - throw new JsonException(String.Format( + } else { + if (! t_data.IsDictionary) { + + if (! reader.SkipNonMembers) { + throw new JsonException (String.Format ( "The type {0} doesn't have the " + "property '{1}'", inst_type, property)); - } - else - { - ReadSkip(reader); + } else { + ReadSkip (reader); continue; } } - ((IDictionary)instance).Add( - property, ReadValue( + ((IDictionary) instance).Add ( + property, ReadValue ( t_data.ElementType, reader)); } @@ -536,74 +499,65 @@ private static object ReadValue(Type inst_type, JsonReader reader) return instance; } - private static IJsonWrapper ReadValue(WrapperFactory factory, + private static IJsonWrapper ReadValue (WrapperFactory factory, JsonReader reader) { - reader.Read(); + reader.Read (); if (reader.Token == JsonToken.ArrayEnd || reader.Token == JsonToken.Null) return null; - IJsonWrapper instance = factory(); + IJsonWrapper instance = factory (); - if (reader.Token == JsonToken.String) - { - instance.SetString((string)reader.Value); + if (reader.Token == JsonToken.String) { + instance.SetString ((string) reader.Value); return instance; } - if (reader.Token == JsonToken.Double) - { - instance.SetDouble((double)reader.Value); + if (reader.Token == JsonToken.Double) { + instance.SetDouble ((double) reader.Value); return instance; } - if (reader.Token == JsonToken.Int) - { - instance.SetInt((int)reader.Value); + if (reader.Token == JsonToken.Int) { + instance.SetInt ((int) reader.Value); return instance; } - if (reader.Token == JsonToken.Long) - { - instance.SetLong((long)reader.Value); + if (reader.Token == JsonToken.Long) { + instance.SetLong ((long) reader.Value); return instance; } - if (reader.Token == JsonToken.Boolean) - { - instance.SetBoolean((bool)reader.Value); + if (reader.Token == JsonToken.Boolean) { + instance.SetBoolean ((bool) reader.Value); return instance; } - if (reader.Token == JsonToken.ArrayStart) - { - instance.SetJsonType(JsonType.Array); + if (reader.Token == JsonToken.ArrayStart) { + instance.SetJsonType (JsonType.Array); - while (true) - { - IJsonWrapper item = ReadValue(factory, reader); + while (true) { + IJsonWrapper item = ReadValue (factory, reader); if (item == null && reader.Token == JsonToken.ArrayEnd) break; - ((IList)instance).Add(item); + ((IList) instance).Add (item); } } - else if (reader.Token == JsonToken.ObjectStart) - { - instance.SetJsonType(JsonType.Object); + else if (reader.Token == JsonToken.ObjectStart) { + instance.SetJsonType (JsonType.Object); - while (true) - { - reader.Read(); + while (true) { + reader.Read (); if (reader.Token == JsonToken.ObjectEnd) break; - string property = (string)reader.Value; + string property = (string) reader.Value; - ((IDictionary)instance)[property] = ReadValue( + ((IDictionary) instance)[property] = ReadValue ( factory, reader); } @@ -612,235 +566,206 @@ private static IJsonWrapper ReadValue(WrapperFactory factory, return instance; } - private static void ReadSkip(JsonReader reader) + private static void ReadSkip (JsonReader reader) { - ToWrapper( - delegate { return new JsonMockWrapper(); }, reader); + ToWrapper ( + delegate { return new JsonMockWrapper (); }, reader); } - private static void RegisterBaseExporters() + private static void RegisterBaseExporters () { // This method is only called from the static initializer, // so there is no need to explicitly lock any static members here - base_exporters_table[typeof(byte)] = - delegate (object obj, JsonWriter writer) - { - writer.Write(Convert.ToInt32((byte)obj)); + base_exporters_table[typeof (byte)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((byte) obj)); }; - base_exporters_table[typeof(char)] = - delegate (object obj, JsonWriter writer) - { - writer.Write(Convert.ToString((char)obj)); + base_exporters_table[typeof (char)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToString ((char) obj)); }; - base_exporters_table[typeof(DateTime)] = - delegate (object obj, JsonWriter writer) - { - writer.Write(Convert.ToString((DateTime)obj, + base_exporters_table[typeof (DateTime)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToString ((DateTime) obj, datetime_format)); }; - base_exporters_table[typeof(decimal)] = - delegate (object obj, JsonWriter writer) - { - writer.Write((decimal)obj); + base_exporters_table[typeof (decimal)] = + delegate (object obj, JsonWriter writer) { + writer.Write ((decimal) obj); }; - base_exporters_table[typeof(sbyte)] = - delegate (object obj, JsonWriter writer) - { - writer.Write(Convert.ToInt32((sbyte)obj)); + base_exporters_table[typeof (sbyte)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((sbyte) obj)); }; - base_exporters_table[typeof(short)] = - delegate (object obj, JsonWriter writer) - { - writer.Write(Convert.ToInt32((short)obj)); + base_exporters_table[typeof (short)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((short) obj)); }; - base_exporters_table[typeof(ushort)] = - delegate (object obj, JsonWriter writer) - { - writer.Write(Convert.ToInt32((ushort)obj)); + base_exporters_table[typeof (ushort)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((ushort) obj)); }; - base_exporters_table[typeof(uint)] = - delegate (object obj, JsonWriter writer) - { - writer.Write(Convert.ToUInt64((uint)obj)); + base_exporters_table[typeof (uint)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToUInt64 ((uint) obj)); }; - base_exporters_table[typeof(ulong)] = - delegate (object obj, JsonWriter writer) - { - writer.Write((ulong)obj); + base_exporters_table[typeof (ulong)] = + delegate (object obj, JsonWriter writer) { + writer.Write ((ulong) obj); }; base_exporters_table[typeof(DateTimeOffset)] = - delegate (object obj, JsonWriter writer) - { + delegate (object obj, JsonWriter writer) { writer.Write(((DateTimeOffset)obj).ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz", datetime_format)); }; } - private static void RegisterBaseImporters() + private static void RegisterBaseImporters () { - ImporterFunc importer; - // This method is only called from the static initializer, // so there is no need to explicitly lock any static members here - importer = delegate (object input) - { - return Convert.ToByte((int)input); + ImporterFunc importer; + + importer = delegate (object input) { + return Convert.ToByte ((int) input); }; - RegisterImporter(base_importers_table, typeof(int), - typeof(byte), importer); + RegisterImporter (base_importers_table, typeof (int), + typeof (byte), importer); - importer = delegate (object input) - { - return Convert.ToUInt64((int)input); + importer = delegate (object input) { + return Convert.ToUInt64 ((int) input); }; - RegisterImporter(base_importers_table, typeof(int), - typeof(ulong), importer); + RegisterImporter (base_importers_table, typeof (int), + typeof (ulong), importer); - importer = delegate (object input) - { + importer = delegate (object input) { return Convert.ToInt64((int)input); }; RegisterImporter(base_importers_table, typeof(int), typeof(long), importer); - importer = delegate (object input) - { - return Convert.ToSByte((int)input); + importer = delegate (object input) { + return Convert.ToSByte ((int) input); }; - RegisterImporter(base_importers_table, typeof(int), - typeof(sbyte), importer); + RegisterImporter (base_importers_table, typeof (int), + typeof (sbyte), importer); - importer = delegate (object input) - { - return Convert.ToInt16((int)input); + importer = delegate (object input) { + return Convert.ToInt16 ((int) input); }; - RegisterImporter(base_importers_table, typeof(int), - typeof(short), importer); + RegisterImporter (base_importers_table, typeof (int), + typeof (short), importer); - importer = delegate (object input) - { - return Convert.ToUInt16((int)input); + importer = delegate (object input) { + return Convert.ToUInt16 ((int) input); }; - RegisterImporter(base_importers_table, typeof(int), - typeof(ushort), importer); + RegisterImporter (base_importers_table, typeof (int), + typeof (ushort), importer); - importer = delegate (object input) - { - return Convert.ToUInt32((int)input); + importer = delegate (object input) { + return Convert.ToUInt32 ((int) input); }; - RegisterImporter(base_importers_table, typeof(int), - typeof(uint), importer); + RegisterImporter (base_importers_table, typeof (int), + typeof (uint), importer); - importer = delegate (object input) - { - return Convert.ToSingle((int)input); + importer = delegate (object input) { + return Convert.ToSingle ((int) input); }; - RegisterImporter(base_importers_table, typeof(int), - typeof(float), importer); + RegisterImporter (base_importers_table, typeof (int), + typeof (float), importer); - importer = delegate (object input) - { - return Convert.ToDouble((int)input); + importer = delegate (object input) { + return Convert.ToDouble ((int) input); }; - RegisterImporter(base_importers_table, typeof(int), - typeof(double), importer); + RegisterImporter (base_importers_table, typeof (int), + typeof (double), importer); - importer = delegate (object input) - { - return Convert.ToDecimal((double)input); + importer = delegate (object input) { + return Convert.ToDecimal ((double) input); }; - RegisterImporter(base_importers_table, typeof(double), - typeof(decimal), importer); + RegisterImporter (base_importers_table, typeof (double), + typeof (decimal), importer); - importer = delegate (object input) - { + importer = delegate (object input) { return Convert.ToSingle((double)input); }; RegisterImporter(base_importers_table, typeof(double), typeof(float), importer); - importer = delegate (object input) - { - return Convert.ToUInt32((long)input); + importer = delegate (object input) { + return Convert.ToUInt32 ((long) input); }; - RegisterImporter(base_importers_table, typeof(long), - typeof(uint), importer); + RegisterImporter (base_importers_table, typeof (long), + typeof (uint), importer); - importer = delegate (object input) - { - return Convert.ToChar((string)input); + importer = delegate (object input) { + return Convert.ToChar ((string) input); }; - RegisterImporter(base_importers_table, typeof(string), - typeof(char), importer); + RegisterImporter (base_importers_table, typeof (string), + typeof (char), importer); - importer = delegate (object input) - { - return Convert.ToDateTime((string)input, datetime_format); + importer = delegate (object input) { + return Convert.ToDateTime ((string) input, datetime_format); }; - RegisterImporter(base_importers_table, typeof(string), - typeof(DateTime), importer); + RegisterImporter (base_importers_table, typeof (string), + typeof (DateTime), importer); - importer = delegate (object input) - { + importer = delegate (object input) { return DateTimeOffset.Parse((string)input, datetime_format); }; RegisterImporter(base_importers_table, typeof(string), typeof(DateTimeOffset), importer); } - private static void RegisterImporter( + private static void RegisterImporter ( IDictionary> table, Type json_type, Type value_type, ImporterFunc importer) { - if (!table.ContainsKey(json_type)) - table.Add(json_type, new Dictionary()); + if (! table.ContainsKey (json_type)) + table.Add (json_type, new Dictionary ()); table[json_type][value_type] = importer; } - private static void WriteValue(object obj, JsonWriter writer, + private static void WriteValue (object obj, JsonWriter writer, bool writer_is_private, int depth) { if (depth > max_nesting_depth) - throw new JsonException( - String.Format("Max allowed object depth reached while " + + throw new JsonException ( + String.Format ("Max allowed object depth reached while " + "trying to export from type {0}", - obj.GetType())); + obj.GetType ())); - if (obj == null) - { - writer.Write(null); + if (obj == null) { + writer.Write (null); return; } - if (obj is IJsonWrapper) - { + if (obj is IJsonWrapper) { if (writer_is_private) - writer.TextWriter.Write(((IJsonWrapper)obj).ToJson()); + writer.TextWriter.Write (((IJsonWrapper) obj).ToJson ()); else - ((IJsonWrapper)obj).ToJson(writer); + ((IJsonWrapper) obj).ToJson (writer); return; } - if (obj is String) - { - writer.Write((string)obj); + if (obj is String) { + writer.Write ((string) obj); return; } - if (obj is Double) - { - writer.Write((double)obj); + if (obj is Double) { + writer.Write ((double) obj); return; } @@ -850,70 +775,75 @@ private static void WriteValue(object obj, JsonWriter writer, return; } - if (obj is Int32) - { - writer.Write((int)obj); + if (obj is Int32) { + writer.Write ((int) obj); return; } - if (obj is Boolean) - { - writer.Write((bool)obj); + if (obj is Boolean) { + writer.Write ((bool) obj); return; } - if (obj is Int64) - { - writer.Write((long)obj); + if (obj is Int64) { + writer.Write ((long) obj); return; } - if (obj is Array) - { - writer.WriteArrayStart(); + if (obj is Array) { + writer.WriteArrayStart (); - foreach (object elem in (Array)obj) - WriteValue(elem, writer, writer_is_private, depth + 1); + foreach (object elem in (Array) obj) + WriteValue (elem, writer, writer_is_private, depth + 1); - writer.WriteArrayEnd(); + writer.WriteArrayEnd (); return; } - if (obj is IList) - { - writer.WriteArrayStart(); - foreach (object elem in (IList)obj) - WriteValue(elem, writer, writer_is_private, depth + 1); - writer.WriteArrayEnd(); + if (obj is IList) { + writer.WriteArrayStart (); + foreach (object elem in (IList) obj) + WriteValue (elem, writer, writer_is_private, depth + 1); + writer.WriteArrayEnd (); return; } - if (obj is IDictionary dictionary) - { - writer.WriteObjectStart(); - foreach (DictionaryEntry entry in dictionary) - { + if (obj is IDictionary dictionary) { + writer.WriteObjectStart (); + foreach (DictionaryEntry entry in dictionary) { var propertyName = entry.Key is string key ? key : Convert.ToString(entry.Key, CultureInfo.InvariantCulture); - writer.WritePropertyName(propertyName); - WriteValue(entry.Value, writer, writer_is_private, + writer.WritePropertyName (propertyName); + WriteValue (entry.Value, writer, writer_is_private, depth + 1); } - writer.WriteObjectEnd(); + writer.WriteObjectEnd (); return; } - Type obj_type = obj.GetType(); + Type obj_type = obj.GetType (); // See if there's a custom exporter for the object - lock (custom_exporters_table_lock) - { - if (custom_exporters_table.TryGetValue(obj_type, out ExporterFunc customExporter)) - { + //if (custom_exporters_table.ContainsKey (obj_type)) { + // ExporterFunc exporter = custom_exporters_table[obj_type]; + // exporter (obj, writer); + + // return; + //} + + //// If not, maybe there's a base exporter + //if (base_exporters_table.ContainsKey (obj_type)) { + // ExporterFunc exporter = base_exporters_table[obj_type]; + // exporter (obj, writer); + + // return; + //} + lock (custom_exporters_table_lock) { + if (custom_exporters_table.TryGetValue(obj_type, out ExporterFunc customExporter)) { customExporter(obj, writer); return; @@ -921,188 +851,175 @@ private static void WriteValue(object obj, JsonWriter writer, } // If not, maybe there's a base exporter - if (base_exporters_table.TryGetValue(obj_type, out ExporterFunc baseExporter)) - { + if (base_exporters_table.TryGetValue(obj_type, out ExporterFunc baseExporter)) { baseExporter(obj, writer); return; } // Last option, let's see if it's an enum - if (obj is Enum) - { - Type e_type = Enum.GetUnderlyingType(obj_type); - - if (e_type == typeof(long)) - writer.Write((long)obj); - else if (e_type == typeof(uint)) - writer.Write((uint)obj); - else if (e_type == typeof(ulong)) - writer.Write((ulong)obj); + if (obj is Enum) { + Type e_type = Enum.GetUnderlyingType (obj_type); + + if (e_type == typeof (long)) + writer.Write ((long) obj); + else if (e_type == typeof (uint)) + writer.Write ((uint) obj); + else if (e_type == typeof (ulong)) + writer.Write ((ulong) obj); else if (e_type == typeof(ushort)) - writer.Write((ushort)obj); + writer.Write ((ushort)obj); else if (e_type == typeof(short)) - writer.Write((short)obj); + writer.Write ((short)obj); else if (e_type == typeof(byte)) - writer.Write((byte)obj); + writer.Write ((byte)obj); else if (e_type == typeof(sbyte)) - writer.Write((sbyte)obj); + writer.Write ((sbyte)obj); else - writer.Write((int)obj); + writer.Write ((int) obj); return; } // Okay, so it looks like the input should be exported as an // object - AddTypeProperties(obj_type); + AddTypeProperties (obj_type); IList props = type_properties[obj_type]; - writer.WriteObjectStart(); - foreach (PropertyMetadata p_data in props) - { - if (p_data.IsField) - { - writer.WritePropertyName(p_data.Info.Name); - WriteValue(((FieldInfo)p_data.Info).GetValue(obj), + writer.WriteObjectStart (); + foreach (PropertyMetadata p_data in props) { + if (p_data.IsField) { + writer.WritePropertyName (p_data.Info.Name); + WriteValue (((FieldInfo) p_data.Info).GetValue (obj), writer, writer_is_private, depth + 1); } - else - { - PropertyInfo p_info = (PropertyInfo)p_data.Info; + else { + PropertyInfo p_info = (PropertyInfo) p_data.Info; - if (p_info.CanRead) - { - writer.WritePropertyName(p_data.Info.Name); - WriteValue(p_info.GetValue(obj, null), + if (p_info.CanRead) { + writer.WritePropertyName (p_data.Info.Name); + WriteValue (p_info.GetValue (obj, null), writer, writer_is_private, depth + 1); } } } - writer.WriteObjectEnd(); + writer.WriteObjectEnd (); } #endregion - public static string ToJson(object obj) + public static string ToJson (object obj) { - lock (static_writer_lock) - { - static_writer.Reset(); + lock (static_writer_lock) { + static_writer.Reset (); - WriteValue(obj, static_writer, true, 0); + WriteValue (obj, static_writer, true, 0); - return static_writer.ToString(); + return static_writer.ToString (); } } - public static void ToJson(object obj, JsonWriter writer) + public static void ToJson (object obj, JsonWriter writer) { - WriteValue(obj, writer, false, 0); + WriteValue (obj, writer, false, 0); } - public static JsonData ToObject(JsonReader reader) + public static JsonData ToObject (JsonReader reader) { - return (JsonData)ToWrapper( - delegate { return new JsonData(); }, reader); + return (JsonData) ToWrapper ( + delegate { return new JsonData (); }, reader); } - public static JsonData ToObject(TextReader reader) + public static JsonData ToObject (TextReader reader) { - JsonReader json_reader = new JsonReader(reader); + JsonReader json_reader = new JsonReader (reader); - return (JsonData)ToWrapper( - delegate { return new JsonData(); }, json_reader); + return (JsonData) ToWrapper ( + delegate { return new JsonData (); }, json_reader); } - public static JsonData ToObject(string json) + public static JsonData ToObject (string json) { - return (JsonData)ToWrapper( - delegate { return new JsonData(); }, json); + return (JsonData) ToWrapper ( + delegate { return new JsonData (); }, json); } - public static T ToObject(JsonReader reader) + public static T ToObject (JsonReader reader) { - return (T)ReadValue(typeof(T), reader); + return (T) ReadValue (typeof (T), reader); } - public static T ToObject(TextReader reader) + public static T ToObject (TextReader reader) { - JsonReader json_reader = new JsonReader(reader); + JsonReader json_reader = new JsonReader (reader); - return (T)ReadValue(typeof(T), json_reader); + return (T) ReadValue (typeof (T), json_reader); } - public static T ToObject(string json) + public static T ToObject (string json) { - JsonReader reader = new JsonReader(json); + JsonReader reader = new JsonReader (json); - return (T)ReadValue(typeof(T), reader); + return (T) ReadValue (typeof (T), reader); } - public static object ToObject(string json, Type ConvertType) + public static object ToObject(string json, Type ConvertType ) { JsonReader reader = new JsonReader(json); return ReadValue(ConvertType, reader); } - public static IJsonWrapper ToWrapper(WrapperFactory factory, + public static IJsonWrapper ToWrapper (WrapperFactory factory, JsonReader reader) { - return ReadValue(factory, reader); + return ReadValue (factory, reader); } - public static IJsonWrapper ToWrapper(WrapperFactory factory, + public static IJsonWrapper ToWrapper (WrapperFactory factory, string json) { - JsonReader reader = new JsonReader(json); + JsonReader reader = new JsonReader (json); - return ReadValue(factory, reader); + return ReadValue (factory, reader); } - public static void RegisterExporter(ExporterFunc exporter) + public static void RegisterExporter (ExporterFunc exporter) { ExporterFunc exporter_wrapper = - delegate (object obj, JsonWriter writer) - { - exporter((T)obj, writer); + delegate (object obj, JsonWriter writer) { + exporter ((T) obj, writer); }; - lock (custom_exporters_table_lock) - { - custom_exporters_table[typeof(T)] = exporter_wrapper; + lock (custom_exporters_table_lock) { + custom_exporters_table[typeof (T)] = exporter_wrapper; } } - public static void RegisterImporter( + public static void RegisterImporter ( ImporterFunc importer) { ImporterFunc importer_wrapper = - delegate (object input) - { - return importer((TJson)input); + delegate (object input) { + return importer ((TJson) input); }; - lock (custom_importers_table_lock) - { - RegisterImporter(custom_importers_table, typeof(TJson), - typeof(TValue), importer_wrapper); + lock (custom_importers_table_lock) { + RegisterImporter (custom_importers_table, typeof (TJson), + typeof (TValue), importer_wrapper); } } - public static void UnregisterExporters() + public static void UnregisterExporters () { - lock (custom_exporters_table_lock) - { + lock (custom_exporters_table_lock) { custom_exporters_table.Clear(); } } - public static void UnregisterImporters() + public static void UnregisterImporters () { - lock (custom_importers_table_lock) - { + lock (custom_importers_table_lock) { custom_importers_table.Clear(); } } From ad73cb35c317bdccb994a0ecea9473a91ddbfe34 Mon Sep 17 00:00:00 2001 From: DaveBlack Date: Tue, 29 Aug 2023 16:02:47 -0500 Subject: [PATCH 3/4] - remove commented-out code --- src/LitJson/JsonMapper.cs | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/src/LitJson/JsonMapper.cs b/src/LitJson/JsonMapper.cs index b4a447c..143ddaa 100644 --- a/src/LitJson/JsonMapper.cs +++ b/src/LitJson/JsonMapper.cs @@ -344,15 +344,6 @@ private static object ReadValue (Type inst_type, JsonReader reader) // If there's a custom importer that fits, use it lock (custom_importers_table_lock) { - //if (custom_importers_table.ContainsKey (json_type) && - // custom_importers_table[json_type].ContainsKey ( - // value_type)) { - - // ImporterFunc importer = - // custom_importers_table[json_type][value_type]; - - // return importer (reader.Value); - //} if (custom_importers_table.TryGetValue(json_type, out IDictionary customImporterTablesValue) && customImporterTablesValue.TryGetValue(value_type, out ImporterFunc customImporter)) { @@ -361,15 +352,6 @@ private static object ReadValue (Type inst_type, JsonReader reader) } // Maybe there's a base importer that works - //if (base_importers_table.ContainsKey (json_type) && - // base_importers_table[json_type].ContainsKey ( - // value_type)) { - - // ImporterFunc importer = - // base_importers_table[json_type][value_type]; - - // return importer (reader.Value); - //} if (base_importers_table.TryGetValue(json_type, out IDictionary baseImporterTablesValue) && baseImporterTablesValue.TryGetValue(value_type, out ImporterFunc baseImporter)) { @@ -828,20 +810,6 @@ private static void WriteValue (object obj, JsonWriter writer, Type obj_type = obj.GetType (); // See if there's a custom exporter for the object - //if (custom_exporters_table.ContainsKey (obj_type)) { - // ExporterFunc exporter = custom_exporters_table[obj_type]; - // exporter (obj, writer); - - // return; - //} - - //// If not, maybe there's a base exporter - //if (base_exporters_table.ContainsKey (obj_type)) { - // ExporterFunc exporter = base_exporters_table[obj_type]; - // exporter (obj, writer); - - // return; - //} lock (custom_exporters_table_lock) { if (custom_exporters_table.TryGetValue(obj_type, out ExporterFunc customExporter)) { customExporter(obj, writer); From 9899787f1769f6ee996500ff9cd1e1ee32a46af5 Mon Sep 17 00:00:00 2001 From: DaveBlack Date: Tue, 29 Aug 2023 16:05:17 -0500 Subject: [PATCH 4/4] - fix formatting --- src/LitJson/JsonMapper.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LitJson/JsonMapper.cs b/src/LitJson/JsonMapper.cs index 143ddaa..fc10b28 100644 --- a/src/LitJson/JsonMapper.cs +++ b/src/LitJson/JsonMapper.cs @@ -359,10 +359,10 @@ private static object ReadValue (Type inst_type, JsonReader reader) } // Maybe it's an enum -#if NETSTANDARD1_5 + #if NETSTANDARD1_5 if (value_type.IsEnum()) return Enum.ToObject (value_type, reader.Value); -#else + #else if (value_type.IsEnum) return Enum.ToObject (value_type, reader.Value); #endif @@ -559,7 +559,7 @@ private static void RegisterBaseExporters () // This method is only called from the static initializer, // so there is no need to explicitly lock any static members here base_exporters_table[typeof (byte)] = - delegate (object obj, JsonWriter writer) { + delegate (object obj, JsonWriter writer) { writer.Write (Convert.ToInt32 ((byte) obj)); };