Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 91 additions & 32 deletions src/LitJson/JsonMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ internal struct ArrayMetadata
private Type element_type;
private bool is_array;
private bool is_list;
private bool is_set;


public Type ElementType {
Expand All @@ -54,6 +55,11 @@ public bool IsList {
get { return is_list; }
set { is_list = value; }
}

public bool IsSet {
get { return is_set; }
set { is_set = value; }
}
}


Expand Down Expand Up @@ -173,17 +179,27 @@ private static void AddArrayMetadata (Type type)
if (type.GetInterface ("System.Collections.IList") != null)
data.IsList = true;

foreach (PropertyInfo p_info in type.GetProperties ()) {
if (p_info.Name != "Item")
continue;
if (data.IsArray || data.IsList) {
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.Length != 1)
continue;

if (parameters[0].ParameterType == typeof (int))
data.ElementType = p_info.PropertyType;
if (parameters[0].ParameterType == typeof (int))
data.ElementType = p_info.PropertyType;
}
}
else {
var iSet = GetGenericInterface(type, typeof(ISet<>));
if (iSet != null) {
data.IsSet = true;
var targetType = iSet.GetGenericArguments()[0];
data.ElementType = targetType;
}
}

lock (array_metadata_lock) {
Expand All @@ -195,6 +211,19 @@ private static void AddArrayMetadata (Type type)
}
}

private static Type GetGenericInterface(Type type, Type generic)
{
Type[] interfaces = type.GetInterfaces();
for (int i = 0; i < interfaces.Length; ++i) {
Type this_interface = interfaces[i];
if (this_interface.IsGenericType && this_interface.GetGenericTypeDefinition() == generic) {
return this_interface;
}
}

return null;
}

private static void AddObjectMetadata (Type type)
{
if (object_metadata.ContainsKey (type))
Expand Down Expand Up @@ -390,41 +419,62 @@ private static object ReadValue (Type inst_type, JsonReader reader)
AddArrayMetadata (inst_type);
ArrayMetadata t_data = array_metadata[inst_type];

if (! t_data.IsArray && ! t_data.IsList)
if (!t_data.IsArray && !t_data.IsList && !t_data.IsSet)
throw new JsonException (String.Format (
"Type {0} can't act as an array",
"Type {0} can't act as an array or set",
inst_type));

IList list;
Type elem_type;
if (t_data.IsArray || t_data.IsList) {
IList list;

if (! t_data.IsArray) {
list = (IList) Activator.CreateInstance (inst_type);
elem_type = t_data.ElementType;
} else {
list = new ArrayList ();
elem_type = inst_type.GetElementType ();
}
if (! t_data.IsArray) {
list = (IList) Activator.CreateInstance (inst_type);
elem_type = t_data.ElementType;
} else {
list = new ArrayList ();
elem_type = inst_type.GetElementType ();
}

list.Clear();
list.Clear ();

while (true) {
object item = ReadValue (elem_type, reader);
if (item == null && reader.Token == JsonToken.ArrayEnd)
break;
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) {
int n = list.Count;
instance = Array.CreateInstance (elem_type, n);
if (t_data.IsArray) {
int n = list.Count;
instance = Array.CreateInstance (elem_type, n);

for (int i = 0; i < n; i++)
((Array) instance).SetValue (list[i], i);
} else
instance = list;
for (int i = 0; i < n; i++)
((Array) instance).SetValue (list[i], i);
} else
instance = list;
} else {
elem_type = t_data.ElementType;
Type set_type = typeof (ISet<>).MakeGenericType (elem_type);
object set = Activator.CreateInstance (inst_type);

MethodInfo addMethod = set_type.GetMethod ("Add");
if (addMethod != null) {
while (true) {
object item = ReadValue (elem_type, reader);
if (item == null && reader.Token == JsonToken.ArrayEnd)
break;

addMethod.Invoke (set, new[] { item });
}

instance = set;
} else {
throw new JsonException (String.Format (
"Type {0} can't act as an set", inst_type));
}
}
} else if (reader.Token == JsonToken.ObjectStart) {
AddObjectMetadata (value_type);
ObjectMetadata t_data = object_metadata[value_type];
Expand Down Expand Up @@ -792,6 +842,15 @@ private static void WriteValue (object obj, JsonWriter writer,
return;
}

if (GetGenericInterface (obj.GetType (), typeof (ISet<>)) != null) {
writer.WriteArrayStart ();
foreach (object elem in (IEnumerable) obj)
WriteValue (elem, writer, writer_is_private, depth + 1);
writer.WriteArrayEnd ();

return;
}

if (obj is IDictionary dictionary) {
writer.WriteObjectStart ();
foreach (DictionaryEntry entry in dictionary) {
Expand Down