Cleaned up the Json contract resolver, fixed user mention deserialization
This commit is contained in:
@@ -27,7 +27,7 @@ namespace Discord.API
|
|||||||
[JsonProperty("mention_everyone")]
|
[JsonProperty("mention_everyone")]
|
||||||
public Optional<bool> MentionEveryone { get; set; }
|
public Optional<bool> MentionEveryone { get; set; }
|
||||||
[JsonProperty("mentions")]
|
[JsonProperty("mentions")]
|
||||||
public Optional<ObjectOrId<User>[]> UserMentions { get; set; }
|
public Optional<EntityOrId<User>[]> UserMentions { get; set; }
|
||||||
[JsonProperty("mention_roles")]
|
[JsonProperty("mention_roles")]
|
||||||
public Optional<ulong[]> RoleMentions { get; set; }
|
public Optional<ulong[]> RoleMentions { get; set; }
|
||||||
[JsonProperty("attachments")]
|
[JsonProperty("attachments")]
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
namespace Discord.API
|
namespace Discord.API
|
||||||
{
|
{
|
||||||
public struct ObjectOrId<T>
|
public struct EntityOrId<T>
|
||||||
{
|
{
|
||||||
public ulong Id { get; }
|
public ulong Id { get; }
|
||||||
public T Object { get; }
|
public T Object { get; }
|
||||||
|
|
||||||
public ObjectOrId(ulong id)
|
public EntityOrId(ulong id)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
Object = default(T);
|
Object = default(T);
|
||||||
}
|
}
|
||||||
public ObjectOrId(T obj)
|
public EntityOrId(T obj)
|
||||||
{
|
{
|
||||||
Id = 0;
|
Id = 0;
|
||||||
Object = obj;
|
Object = obj;
|
||||||
@@ -1,28 +1,38 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
namespace Discord.Net.Converters
|
namespace Discord.Net.Converters
|
||||||
{
|
{
|
||||||
internal class UInt64ArrayConverter : JsonConverter
|
internal class ArrayConverter<T> : JsonConverter
|
||||||
{
|
{
|
||||||
public static readonly UInt64ArrayConverter Instance = new UInt64ArrayConverter();
|
public static ArrayConverter<T> Instance;
|
||||||
|
|
||||||
|
private readonly JsonConverter _innerConverter;
|
||||||
|
|
||||||
public override bool CanConvert(Type objectType) => true;
|
public override bool CanConvert(Type objectType) => true;
|
||||||
public override bool CanRead => true;
|
public override bool CanRead => true;
|
||||||
public override bool CanWrite => true;
|
public override bool CanWrite => true;
|
||||||
|
|
||||||
|
public ArrayConverter(JsonConverter innerConverter)
|
||||||
|
{
|
||||||
|
_innerConverter = innerConverter;
|
||||||
|
}
|
||||||
|
|
||||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
var result = new List<ulong>();
|
var result = new List<T>();
|
||||||
if (reader.TokenType == JsonToken.StartArray)
|
if (reader.TokenType == JsonToken.StartArray)
|
||||||
{
|
{
|
||||||
reader.Read();
|
reader.Read();
|
||||||
while (reader.TokenType != JsonToken.EndArray)
|
while (reader.TokenType != JsonToken.EndArray)
|
||||||
{
|
{
|
||||||
ulong id = ulong.Parse((string)reader.Value, NumberStyles.None, CultureInfo.InvariantCulture);
|
T obj;
|
||||||
result.Add(id);
|
if (_innerConverter != null)
|
||||||
|
obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer);
|
||||||
|
else
|
||||||
|
obj = serializer.Deserialize<T>(reader);
|
||||||
|
result.Add(obj);
|
||||||
reader.Read();
|
reader.Read();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,9 +43,15 @@ namespace Discord.Net.Converters
|
|||||||
if (value != null)
|
if (value != null)
|
||||||
{
|
{
|
||||||
writer.WriteStartArray();
|
writer.WriteStartArray();
|
||||||
var a = (ulong[])value;
|
var a = (T[])value;
|
||||||
for (int i = 0; i < a.Length; i++)
|
for (int i = 0; i < a.Length; i++)
|
||||||
writer.WriteValue(a[i].ToString(CultureInfo.InvariantCulture));
|
{
|
||||||
|
if (_innerConverter != null)
|
||||||
|
_innerConverter.WriteJson(writer, a[i], serializer);
|
||||||
|
else
|
||||||
|
serializer.Serialize(writer, a[i], typeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
writer.WriteEndArray();
|
writer.WriteEndArray();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -23,7 +23,7 @@ namespace Discord.Net.Converters
|
|||||||
if (propInfo != null)
|
if (propInfo != null)
|
||||||
{
|
{
|
||||||
JsonConverter converter;
|
JsonConverter converter;
|
||||||
var type = propInfo.PropertyType;
|
Type type = propInfo.PropertyType;
|
||||||
Type genericType = type.IsConstructedGenericType ? type.GetGenericTypeDefinition() : null;
|
Type genericType = type.IsConstructedGenericType ? type.GetGenericTypeDefinition() : null;
|
||||||
|
|
||||||
if (genericType == typeof(Optional<>))
|
if (genericType == typeof(Optional<>))
|
||||||
@@ -37,29 +37,7 @@ namespace Discord.Net.Converters
|
|||||||
var shouldSerializeDelegate = (Func<object, Delegate, bool>)shouldSerialize.CreateDelegate(typeof(Func<object, Delegate, bool>));
|
var shouldSerializeDelegate = (Func<object, Delegate, bool>)shouldSerialize.CreateDelegate(typeof(Func<object, Delegate, bool>));
|
||||||
property.ShouldSerialize = x => shouldSerializeDelegate(x, getterDelegate);
|
property.ShouldSerialize = x => shouldSerializeDelegate(x, getterDelegate);
|
||||||
|
|
||||||
var converterType = typeof(OptionalConverter<>).MakeGenericType(innerTypeOutput).GetTypeInfo();
|
converter = MakeGenericConverter(propInfo, typeof(OptionalConverter<>), innerTypeOutput);
|
||||||
var instanceField = converterType.GetDeclaredField("Instance");
|
|
||||||
converter = instanceField.GetValue(null) as JsonConverter;
|
|
||||||
if (converter == null)
|
|
||||||
{
|
|
||||||
var innerConverter = GetConverter(propInfo, innerTypeOutput);
|
|
||||||
converter = converterType.DeclaredConstructors.First().Invoke(new object[] { innerConverter }) as JsonConverter;
|
|
||||||
instanceField.SetValue(null, converter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (genericType == typeof(ObjectOrId<>))
|
|
||||||
{
|
|
||||||
var innerTypeOutput = type.GenericTypeArguments[0];
|
|
||||||
|
|
||||||
var converterType = typeof(ObjectOrIdConverter<>).MakeGenericType(innerTypeOutput).GetTypeInfo();
|
|
||||||
var instanceField = converterType.GetDeclaredField("Instance");
|
|
||||||
converter = instanceField.GetValue(null) as JsonConverter;
|
|
||||||
if (converter == null)
|
|
||||||
{
|
|
||||||
var innerConverter = GetConverter(propInfo, innerTypeOutput);
|
|
||||||
converter = converterType.DeclaredConstructors.First().Invoke(new object[] { innerConverter }) as JsonConverter;
|
|
||||||
instanceField.SetValue(null, converter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
converter = GetConverter(propInfo, type);
|
converter = GetConverter(propInfo, type);
|
||||||
@@ -75,9 +53,18 @@ namespace Discord.Net.Converters
|
|||||||
return property;
|
return property;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonConverter GetConverter(MemberInfo member, Type type, TypeInfo typeInfo = null)
|
private static JsonConverter GetConverter(PropertyInfo propInfo, Type type, TypeInfo typeInfo = null, int depth = 0)
|
||||||
{
|
{
|
||||||
bool hasInt53 = member.GetCustomAttribute<Int53Attribute>() != null;
|
if (type.IsArray)
|
||||||
|
return MakeGenericConverter(propInfo, typeof(ArrayConverter<>), type.GetElementType());
|
||||||
|
if (type.IsConstructedGenericType)
|
||||||
|
{
|
||||||
|
Type genericType = type.GetGenericTypeDefinition();
|
||||||
|
if (genericType == typeof(EntityOrId<>))
|
||||||
|
return MakeGenericConverter(propInfo, typeof(UInt64EntityOrIdConverter<>), type.GenericTypeArguments[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasInt53 = propInfo.GetCustomAttribute<Int53Attribute>() != null;
|
||||||
|
|
||||||
//Primitives
|
//Primitives
|
||||||
if (!hasInt53)
|
if (!hasInt53)
|
||||||
@@ -100,10 +87,6 @@ namespace Discord.Net.Converters
|
|||||||
|
|
||||||
if (typeInfo == null) typeInfo = type.GetTypeInfo();
|
if (typeInfo == null) typeInfo = type.GetTypeInfo();
|
||||||
|
|
||||||
//Primitives
|
|
||||||
if (!hasInt53 && typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEnumerable<ulong>)))
|
|
||||||
return UInt64ArrayConverter.Instance;
|
|
||||||
|
|
||||||
//Entities
|
//Entities
|
||||||
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<ulong>)))
|
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<ulong>)))
|
||||||
return UInt64EntityConverter.Instance;
|
return UInt64EntityConverter.Instance;
|
||||||
@@ -117,5 +100,19 @@ namespace Discord.Net.Converters
|
|||||||
{
|
{
|
||||||
return (getter as Func<TOwner, Optional<TValue>>)((TOwner)owner).IsSpecified;
|
return (getter as Func<TOwner, Optional<TValue>>)((TOwner)owner).IsSpecified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static JsonConverter MakeGenericConverter(PropertyInfo propInfo, Type converterType, Type innerType)
|
||||||
|
{
|
||||||
|
var genericType = converterType.MakeGenericType(innerType).GetTypeInfo();
|
||||||
|
var instanceField = genericType.GetDeclaredField("Instance");
|
||||||
|
var converter = instanceField.GetValue(null) as JsonConverter;
|
||||||
|
if (converter == null)
|
||||||
|
{
|
||||||
|
var innerConverter = GetConverter(propInfo, innerType);
|
||||||
|
converter = genericType.DeclaredConstructors.First().Invoke(new object[] { innerConverter }) as JsonConverter;
|
||||||
|
instanceField.SetValue(null, converter);
|
||||||
|
}
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ using System;
|
|||||||
|
|
||||||
namespace Discord.Net.Converters
|
namespace Discord.Net.Converters
|
||||||
{
|
{
|
||||||
internal class ObjectOrIdConverter<T> : JsonConverter
|
internal class UInt64EntityOrIdConverter<T> : JsonConverter
|
||||||
{
|
{
|
||||||
internal static ObjectOrIdConverter<T> Instance;
|
public static UInt64EntityOrIdConverter<T> Instance;
|
||||||
|
|
||||||
private readonly JsonConverter _innerConverter;
|
private readonly JsonConverter _innerConverter;
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ namespace Discord.Net.Converters
|
|||||||
public override bool CanRead => true;
|
public override bool CanRead => true;
|
||||||
public override bool CanWrite => false;
|
public override bool CanWrite => false;
|
||||||
|
|
||||||
public ObjectOrIdConverter(JsonConverter innerConverter)
|
public UInt64EntityOrIdConverter(JsonConverter innerConverter)
|
||||||
{
|
{
|
||||||
_innerConverter = innerConverter;
|
_innerConverter = innerConverter;
|
||||||
}
|
}
|
||||||
@@ -25,9 +25,14 @@ namespace Discord.Net.Converters
|
|||||||
{
|
{
|
||||||
case JsonToken.String:
|
case JsonToken.String:
|
||||||
case JsonToken.Integer:
|
case JsonToken.Integer:
|
||||||
return new ObjectOrId<T>(ulong.Parse(reader.ReadAsString()));
|
return new EntityOrId<T>(ulong.Parse(reader.ReadAsString()));
|
||||||
default:
|
default:
|
||||||
return new ObjectOrId<T>(serializer.Deserialize<T>(reader));
|
T obj;
|
||||||
|
if (_innerConverter != null)
|
||||||
|
obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer);
|
||||||
|
else
|
||||||
|
obj = serializer.Deserialize<T>(reader);
|
||||||
|
return new EntityOrId<T>(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user