Skip to content

Commit

Permalink
now handle different type property name as suggested in #31 and #38
Browse files Browse the repository at this point in the history
  • Loading branch information
manuc66 committed Apr 16, 2018
1 parent 555bd75 commit 493d485
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 2 deletions.
13 changes: 13 additions & 0 deletions JsonSubTypes.Tests/DemoKnownSubTypeWithProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ public void Demo()
Assert.AreEqual("Painter", (persons.Last() as Artist)?.Skill);
}

[Test]
public void DemoDifferentCase()
{
string json = "[{\"Department\":\"Department1\",\"JobTitle\":\"JobTitle1\",\"FirstName\":\"FirstName1\",\"LastName\":\"LastName1\"}," +
"{\"Department\":\"Department1\",\"JobTitle\":\"JobTitle1\",\"FirstName\":\"FirstName1\",\"LastName\":\"LastName1\"}," +
"{\"skill\"" +
":\"Painter\",\"FirstName\":\"FirstName1\",\"LastName\":\"LastName1\"}]";


var persons = JsonConvert.DeserializeObject<ICollection<Person>>(json);
Assert.AreEqual("Painter", (persons.Last() as Artist)?.Skill);
}

[Test]
public void FallBackToPArentWhenNotFound()
{
Expand Down
1 change: 1 addition & 0 deletions JsonSubTypes.Tests/JsonSubTypes.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="BaseIsAnInterfaceTests.cs" />
<Compile Include="DiscriminatorOfDifferentKindTests.cs" />
<Compile Include="TypePropertyCase.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JsonSubTypes\JsonSubTypes.csproj">
Expand Down
134 changes: 134 additions & 0 deletions JsonSubTypes.Tests/TypePropertyCase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using NUnit.Framework;

namespace JsonSubTypes.Tests
{

public class TypePropertyCase
{
public class TypePropertyCase_LowerWithHigher
{
[JsonConverter(typeof(JsonSubtypes), "msgType")]
[JsonSubtypes.KnownSubType(typeof(Foo), 1)]
public abstract class DtoBase
{
public virtual int MsgType { get; set; }
}

class Foo : DtoBase
{
}

[Test]
public void FooParsingCamelCase()
{
var serializeObject = "{\"MsgType\":1}";
var msgType = JsonConvert.DeserializeObject<Foo>(serializeObject).MsgType;
Assert.AreEqual(1, msgType);
Assert.IsInstanceOf<Foo>(JsonConvert.DeserializeObject<DtoBase>(serializeObject));
}

[Test]
public void FooParsingLowerPascalCase()
{
var serializeObject = "{\"msgType\":1}";
Assert.AreEqual(1, JsonConvert.DeserializeObject<Foo>(serializeObject).MsgType);
Assert.IsInstanceOf<Foo>(JsonConvert.DeserializeObject<DtoBase>(serializeObject));
}
}

public class TypePropertyCase_HigherWithLower
{
[JsonConverter(typeof(JsonSubtypes), "MsgType")]
[JsonSubtypes.KnownSubType(typeof(Foo), 1)]
public abstract class DtoBase
{
[JsonProperty("msgType")]
public virtual int MsgType { get; set; }
}

class Foo : DtoBase
{
}

[Test]
public void FooParsingCamelCase()
{
var serializeObject = "{\"MsgType\":1}";
Assert.AreEqual(1, JsonConvert.DeserializeObject<Foo>(serializeObject).MsgType);
Assert.IsInstanceOf<Foo>(JsonConvert.DeserializeObject<DtoBase>(serializeObject));
}

[Test]
public void FooParsingLowerPascalCase()
{
var serializeObject = "{\"msgType\":1}";
Assert.AreEqual(1, JsonConvert.DeserializeObject<Foo>(serializeObject).MsgType);
Assert.IsInstanceOf<Foo>(JsonConvert.DeserializeObject<DtoBase>(serializeObject));
}
}

public class TypePropertyCase_RedirectLowerWithHigher
{
[JsonConverter(typeof(JsonSubtypes), "messageType")]
[JsonSubtypes.KnownSubType(typeof(Foo), 1)]
public abstract class DtoBase
{
[JsonProperty("MessageType")]
public virtual int MsgType { get; set; }
}

class Foo : DtoBase
{
}

[Test]
public void FooParsingCamelCase()
{
var serializeObject = "{\"MessageType\":1}";
Assert.AreEqual(1, JsonConvert.DeserializeObject<Foo>(serializeObject).MsgType);
Assert.IsInstanceOf<Foo>(JsonConvert.DeserializeObject<DtoBase>(serializeObject));
}

[Test]
public void FooParsingLowerPascalCase()
{
var serializeObject = "{\"messageType\":1}";
Assert.AreEqual(1, JsonConvert.DeserializeObject<Foo>(serializeObject).MsgType);
Assert.IsInstanceOf<Foo>(JsonConvert.DeserializeObject<DtoBase>(serializeObject));
}
}

public class TypePropertyCase_RedirectHigherWithLower
{
[JsonConverter(typeof(JsonSubtypes), "MessageType")]
[JsonSubtypes.KnownSubType(typeof(Foo), 1)]
public abstract class DtoBase
{
[JsonProperty("messageType")]
public virtual int MsgType { get; set; }
}

class Foo : DtoBase
{
}

[Test]
public void FooParsingCamelCase()
{
var serializeObject = "{\"MessageType\":1}";
Assert.AreEqual(1, JsonConvert.DeserializeObject<Foo>(serializeObject).MsgType);
Assert.IsInstanceOf<Foo>(JsonConvert.DeserializeObject<DtoBase>(serializeObject));
}

[Test]
public void FooParsingLowerPascalCase()
{
var serializeObject = "{\"messageType\":1}";
Assert.AreEqual(1, JsonConvert.DeserializeObject<Foo>(serializeObject).MsgType);
Assert.IsInstanceOf<Foo>(JsonConvert.DeserializeObject<DtoBase>(serializeObject));
}
}
}
}
24 changes: 22 additions & 2 deletions JsonSubTypes/JsonSubtypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ private static Type GetTypeByPropertyPresence(IDictionary<string, JToken> jObjec
.Select(knownType =>
{
JToken ignore;
if (jObject.TryGetValue(knownType.PropertyName, out ignore))
if (TryGetValueInJson(jObject, knownType.PropertyName, out ignore))
return knownType.SubType;

return null;
Expand All @@ -233,7 +233,7 @@ private static Type GetTypeByPropertyPresence(IDictionary<string, JToken> jObjec
private Type GetTypeFromDiscriminatorValue(IDictionary<string, JToken> jObject, Type parentType)
{
JToken discriminatorToken;
if (!jObject.TryGetValue(TypeMappingPropertyName, out discriminatorToken))
if (!TryGetValueInJson(jObject, TypeMappingPropertyName, out discriminatorToken))
return null;

if (discriminatorToken.Type == JTokenType.Null)
Expand All @@ -247,6 +247,26 @@ private Type GetTypeFromDiscriminatorValue(IDictionary<string, JToken> jObject,

return GetTypeByName(discriminatorToken.Value<string>(), parentType);
}

private static bool TryGetValueInJson(IDictionary<string, JToken> jObject, string propertyName, out JToken value)
{
if (jObject.TryGetValue(propertyName, out value))
{
return true;
}

var matchingProperty = jObject
.Keys
.FirstOrDefault(jsonProperty => string.Equals(jsonProperty, propertyName, StringComparison.OrdinalIgnoreCase));

if (matchingProperty == null)
{
return false;
}

value = jObject[matchingProperty];
return true;
}

private static Type GetTypeByName(string typeName, Type parentType)
{
Expand Down

0 comments on commit 493d485

Please sign in to comment.