Browse Source

Cleaned up the Json contract resolver, fixed user mention deserialization

tags/1.0-rc
RogueException 8 years ago
parent
commit
f93464523e
5 changed files with 65 additions and 47 deletions
  1. +1
    -1
      src/Discord.Net.Core/API/Common/Message.cs
  2. +3
    -3
      src/Discord.Net.Core/API/EntityOrId.cs
  3. +24
    -8
      src/Discord.Net.Core/Net/Converters/ArrayConverter.cs
  4. +27
    -30
      src/Discord.Net.Core/Net/Converters/DiscordContractResolver.cs
  5. +10
    -5
      src/Discord.Net.Core/Net/Converters/UInt64EntityOrIdConverter.cs

+ 1
- 1
src/Discord.Net.Core/API/Common/Message.cs View File

@@ -27,7 +27,7 @@ namespace Discord.API
[JsonProperty("mention_everyone")]
public Optional<bool> MentionEveryone { get; set; }
[JsonProperty("mentions")]
public Optional<ObjectOrId<User>[]> UserMentions { get; set; }
public Optional<EntityOrId<User>[]> UserMentions { get; set; }
[JsonProperty("mention_roles")]
public Optional<ulong[]> RoleMentions { get; set; }
[JsonProperty("attachments")]


src/Discord.Net.Core/API/ObjectOrId.cs → src/Discord.Net.Core/API/EntityOrId.cs View File

@@ -1,16 +1,16 @@
namespace Discord.API
{
public struct ObjectOrId<T>
public struct EntityOrId<T>
{
public ulong Id { get; }
public T Object { get; }

public ObjectOrId(ulong id)
public EntityOrId(ulong id)
{
Id = id;
Object = default(T);
}
public ObjectOrId(T obj)
public EntityOrId(T obj)
{
Id = 0;
Object = obj;

src/Discord.Net.Core/Net/Converters/UInt64ArrayConverter.cs → src/Discord.Net.Core/Net/Converters/ArrayConverter.cs View File

@@ -1,28 +1,38 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;

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 CanRead => true;
public override bool CanWrite => true;

public ArrayConverter(JsonConverter innerConverter)
{
_innerConverter = innerConverter;
}

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)
{
reader.Read();
while (reader.TokenType != JsonToken.EndArray)
{
ulong id = ulong.Parse((string)reader.Value, NumberStyles.None, CultureInfo.InvariantCulture);
result.Add(id);
T obj;
if (_innerConverter != null)
obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer);
else
obj = serializer.Deserialize<T>(reader);
result.Add(obj);
reader.Read();
}
}
@@ -33,9 +43,15 @@ namespace Discord.Net.Converters
if (value != null)
{
writer.WriteStartArray();
var a = (ulong[])value;
var a = (T[])value;
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();
}
else

+ 27
- 30
src/Discord.Net.Core/Net/Converters/DiscordContractResolver.cs View File

@@ -23,7 +23,7 @@ namespace Discord.Net.Converters
if (propInfo != null)
{
JsonConverter converter;
var type = propInfo.PropertyType;
Type type = propInfo.PropertyType;
Type genericType = type.IsConstructedGenericType ? type.GetGenericTypeDefinition() : null;

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>));
property.ShouldSerialize = x => shouldSerializeDelegate(x, getterDelegate);

var converterType = typeof(OptionalConverter<>).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 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);
}
converter = MakeGenericConverter(propInfo, typeof(OptionalConverter<>), innerTypeOutput);
}
else
converter = GetConverter(propInfo, type);
@@ -75,9 +53,18 @@ namespace Discord.Net.Converters
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
if (!hasInt53)
@@ -100,10 +87,6 @@ namespace Discord.Net.Converters

if (typeInfo == null) typeInfo = type.GetTypeInfo();

//Primitives
if (!hasInt53 && typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEnumerable<ulong>)))
return UInt64ArrayConverter.Instance;

//Entities
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<ulong>)))
return UInt64EntityConverter.Instance;
@@ -117,5 +100,19 @@ namespace Discord.Net.Converters
{
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;
}
}
}

src/Discord.Net.Core/Net/Converters/ObjectOrIdConverter.cs → src/Discord.Net.Core/Net/Converters/UInt64EntityOrIdConverter.cs View File

@@ -4,9 +4,9 @@ using System;

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;

@@ -14,7 +14,7 @@ namespace Discord.Net.Converters
public override bool CanRead => true;
public override bool CanWrite => false;

public ObjectOrIdConverter(JsonConverter innerConverter)
public UInt64EntityOrIdConverter(JsonConverter innerConverter)
{
_innerConverter = innerConverter;
}
@@ -25,9 +25,14 @@ namespace Discord.Net.Converters
{
case JsonToken.String:
case JsonToken.Integer:
return new ObjectOrId<T>(ulong.Parse(reader.ReadAsString()));
return new EntityOrId<T>(ulong.Parse(reader.ReadAsString()));
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);
}
}


Loading…
Cancel
Save