Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
manuc66 committed Feb 20, 2020
1 parent ecc1727 commit 97604d9
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 52 deletions.
8 changes: 7 additions & 1 deletion JsonSubTypes.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonSubTypes.Tests.Net35", "JsonSubTypes.Tests.Net35\JsonSubTypes.Tests.Net35.csproj", "{FFBBBE62-26B1-41D1-AEF6-507CC5C0FB9D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NewApi", "NewApi\NewApi.csproj", "{7D93C6F2-85BB-4172-9949-F5398DB7E436}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NewApi", "NewApi\NewApi.csproj", "{7D93C6F2-85BB-4172-9949-F5398DB7E436}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NewApi.Tests", "NewApi.Tests\NewApi.Tests.csproj", "{4F1583A6-4699-4968-B238-3A4317A67A8E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -43,6 +45,10 @@ Global
{7D93C6F2-85BB-4172-9949-F5398DB7E436}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7D93C6F2-85BB-4172-9949-F5398DB7E436}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7D93C6F2-85BB-4172-9949-F5398DB7E436}.Release|Any CPU.Build.0 = Release|Any CPU
{4F1583A6-4699-4968-B238-3A4317A67A8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4F1583A6-4699-4968-B238-3A4317A67A8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F1583A6-4699-4968-B238-3A4317A67A8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F1583A6-4699-4968-B238-3A4317A67A8E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
19 changes: 19 additions & 0 deletions NewApi.Tests/NewApi.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="nunit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\NewApi\NewApi.csproj" />
</ItemGroup>

</Project>
44 changes: 44 additions & 0 deletions NewApi.Tests/UnitTest1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System.Text.Json;
using NUnit.Framework;

namespace NewApi.Tests
{
public class Tests
{
[SetUp]
public void Setup()
{
}

[JsonSubTypeConverter(typeof(JsonSubtypes<Animal>), "Sound")]
[KnownSubType(typeof(Dog), "Bark")]
[KnownSubType(typeof(Cat), "Meow")]
public class Animal
{
public virtual string Sound { get; }
public string Color { get; set; }
}

public class Dog : Animal
{
public override string Sound { get; } = "Bark";
public string Breed { get; set; }
}

public class Cat : Animal
{
public override string Sound { get; } = "Meow";
public bool Declawed { get; set; }
}

[Test]
public void Demo()
{
var animal = JsonSerializer.Deserialize<Animal>("{\"Sound\":\"Bark\",\"Breed\":\"Jack Russell Terrier\"}");
Assert.AreEqual("Jack Russell Terrier", (animal as Dog)?.Breed);

//animal = JsonConvert.DeserializeObject<Animal>("{\"Sound\":\"Meow\",\"Declawed\":\"true\"}");
//Assert.AreEqual(true, (animal as Cat)?.Declawed);
}
}
}
75 changes: 26 additions & 49 deletions NewApi/JsonSubtypes2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@

namespace NewApi
{
public class JsonSubTypeConverterAttribute : JsonConverterAttribute
{
public string DiscriminatorPropertyName { get; }

public JsonSubTypeConverterAttribute(Type converterType, string discriminatorPropertyName) : base(converterType)
{
DiscriminatorPropertyName = discriminatorPropertyName;
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)]
public class KnownSubTypeAttribute : Attribute
{
Expand Down Expand Up @@ -65,7 +75,7 @@ public JsonSubtypes(string jsonDiscriminatorPropertyName)

public override bool CanConvert(Type objectType)
{
return false;
return objectType == typeof(T);
}

public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions serializer)
Expand Down Expand Up @@ -110,17 +120,9 @@ private T ReadJson(ref Utf8JsonReader reader, Type objectType, JsonSerializerOpt
return value;
}

private static JsonReaderException CreateJsonReaderException(ref Utf8JsonReader reader, string message)
private static InvalidOperationException CreateJsonReaderException(ref Utf8JsonReader reader, string message)
{
var lineNumber = 0;
var linePosition = 0;
if (reader is IJsonLineInfo lineInfo && lineInfo.HasLineInfo())
{
lineNumber = lineInfo.LineNumber;
linePosition = lineInfo.LinePosition;
}

return new JsonReaderException(message, reader.Path, lineNumber, linePosition, null);
return new InvalidOperationException(message);
}

private IList ReadArray(ref Utf8JsonReader reader, Type targetType, Type elementType, JsonSerializerOptions serializer)
Expand Down Expand Up @@ -167,20 +169,7 @@ private T ReadObject(ref Utf8JsonReader reader, Type objectType, JsonSerializerO

var targetType = GetType(jObject, objectType, serializer) ?? objectType;

return ThreadStaticReadObject(reader, serializer, jObject, targetType);
}

private static JsonReader CreateAnotherReader(JToken jToken, JsonReader reader)
{
var jObjectReader = jToken.CreateReader();
jObjectReader.Culture = reader.Culture;
jObjectReader.CloseInput = reader.CloseInput;
jObjectReader.SupportMultipleContent = reader.SupportMultipleContent;
jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
jObjectReader.FloatParseHandling = reader.FloatParseHandling;
jObjectReader.DateFormatString = reader.DateFormatString;
jObjectReader.DateParseHandling = reader.DateParseHandling;
return jObjectReader;
return (T)JsonSerializer.Deserialize(jObject.RootElement.GetRawText(), targetType);
}

private Type GetType(JsonDocument jObject, Type parentType)
Expand All @@ -204,7 +193,7 @@ private Type GetType(JsonDocument jObject, Type parentType, JsonSerializerOption
JsonSubtypes<T> lastTypeResolver = null;
JsonSubtypes<T> currentTypeResolver = this;

var jsonConverterCollection = serializer.Converters.OfType<JsonSubtypesConverter>().ToList();
var jsonConverterCollection = serializer.Converters.OfType<JsonSubtypes<T>>().ToList();
while (currentTypeResolver != null && currentTypeResolver != lastTypeResolver)
{
targetType = currentTypeResolver.GetType(jObject, targetType);
Expand All @@ -216,17 +205,17 @@ private Type GetType(JsonDocument jObject, Type parentType, JsonSerializerOption
return targetType;
}

private JsonSubtypes<T> GetTypeResolver(TypeInfo targetType, IEnumerable<JsonSubtypesConverter> jsonConverterCollection)
private JsonSubtypes<T> GetTypeResolver(TypeInfo targetType, IEnumerable<JsonSubtypes<T>> jsonConverterCollection)
{
if (targetType == null)
{
return null;
}

var jsonConverterAttribute = GetAttribute<JsonConverterAttribute>(targetType);
var jsonConverterAttribute = GetAttribute<JsonSubTypeConverterAttribute>(targetType);
if (jsonConverterAttribute != null && ToTypeInfo(typeof(JsonSubtypes<T>)).IsAssignableFrom(ToTypeInfo(jsonConverterAttribute.ConverterType)))
{
return (JsonSubtypes<T>)Activator.CreateInstance(jsonConverterAttribute.ConverterType, jsonConverterAttribute.ConverterParameters);
return (JsonSubtypes<T>)Activator.CreateInstance(jsonConverterAttribute.ConverterType, jsonConverterAttribute.DiscriminatorPropertyName);
}

return jsonConverterCollection
Expand Down Expand Up @@ -322,13 +311,14 @@ private static Type GetTypeFromMapping(NullableDictionary<object, Type> typeMapp
var key = typeMapping.NotNullKeys().FirstOrDefault();
if (key != null)
{
var targetLookupValueType = key.GetType();
var lookupValue = discriminatorToken.ToObject(targetLookupValueType);

if (typeMapping.TryGetValue(lookupValue, out Type targetType))
{
return targetType;
}
throw new NotImplementedException();
//var targetLookupValueType = key.GetType();
//var lookupValue = discriminatorToken.ToObject(targetLookupValueType);

//if (typeMapping.TryGetValue(lookupValue, out Type targetType))
//{
// return targetType;
//}
}

return null;
Expand All @@ -350,19 +340,6 @@ internal virtual Type GetFallbackSubType(Type type)
return GetAttribute<FallBackSubTypeAttribute>(ToTypeInfo(type))?.SubType;
}

private static object ThreadStaticReadObject(ref Utf8JsonReader reader, JsonSerializerOptions serializer, JsonDocument jToken, Type targetType)
{
_reader = CreateAnotherReader(jToken, reader);
_isInsideRead = true;
try
{
return serializer.Deserialize(_reader, targetType);
}
finally
{
_isInsideRead = false;
}
}

private static IEnumerable<T> GetAttributes<T>(TypeInfo typeInfo) where T : Attribute
{
Expand Down
4 changes: 2 additions & 2 deletions NewApi/NewApi.csproj
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.Text.Json" Version="4.6.0" />
<PackageReference Include="System.Text.Json" Version="4.7.1" />
</ItemGroup>

</Project>

0 comments on commit 97604d9

Please sign in to comment.