Skip to content

Commit 0883573

Browse files
committed
Fix #39
1 parent 336cc6a commit 0883573

File tree

3 files changed

+122
-72
lines changed

3 files changed

+122
-72
lines changed

Source/Schema.NET/Schema.NET.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup Label="Build">
44
<TargetFrameworks>netstandard1.1;netstandard2.0</TargetFrameworks>
@@ -10,7 +10,7 @@
1010
</PropertyGroup>
1111

1212
<PropertyGroup Label="Package">
13-
<VersionPrefix>3.7.0</VersionPrefix>
13+
<VersionPrefix>3.7.1</VersionPrefix>
1414
<Authors>Muhammad Rehan Saeed (RehanSaeed.com)</Authors>
1515
<Product>Schema.NET</Product>
1616
<Description>Schema.org objects turned into strongly typed C# POCO classes for use in .NET. All classes can be serialized into JSON/JSON-LD and XML, typically used to represent structured data in the head section of html page.</Description>

Source/Schema.NET/ValuesConverter.cs

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -52,26 +52,7 @@ public override object ReadJson(
5252
var type = mainType.GenericTypeArguments[0].GetUnderlyingTypeFromNullable();
5353
if (tokenType == JsonToken.StartArray)
5454
{
55-
var listType = typeof(List<>).MakeGenericType(type);
56-
if (token.Any(t => !string.IsNullOrEmpty(GetTypeNameFromToken(t))))
57-
{
58-
var list = Activator.CreateInstance(listType);
59-
foreach (var childToken in token.Children())
60-
{
61-
var typeName = GetTypeNameFromToken(childToken);
62-
var builtType = Type.GetType($"{NamespacePrefix}{typeName}");
63-
var child = (Thing)childToken.ToObject(builtType);
64-
listType
65-
.GetRuntimeMethod(nameof(List<object>.Add), new[] { type })
66-
.Invoke(list, new object[] { child });
67-
}
68-
69-
argument = list;
70-
}
71-
else
72-
{
73-
argument = token.ToObject(listType);
74-
}
55+
argument = ReadJsonArray(token, type);
7556
}
7657
else if (type.IsPrimitiveType())
7758
{
@@ -136,8 +117,7 @@ public override object ReadJson(
136117
}
137118
else if (tokenType == JsonToken.StartArray)
138119
{
139-
var arrayType = typeof(List<>).MakeGenericType(type);
140-
args = token.ToObject(arrayType);
120+
args = ReadJsonArray(token, type);
141121
}
142122
else
143123
{
@@ -158,7 +138,6 @@ public override object ReadJson(
158138

159139
var genericType = typeof(OneOrMany<>).MakeGenericType(type);
160140
argument = Activator.CreateInstance(genericType, args);
161-
break;
162141
}
163142
catch
164143
{
@@ -213,6 +192,54 @@ public virtual void WriteObject(JsonWriter writer, object value, JsonSerializer
213192
token.WriteTo(writer);
214193
}
215194

195+
private static object ReadJsonArray(JToken token, Type type)
196+
{
197+
var listType = typeof(List<>).MakeGenericType(type);
198+
var list = Activator.CreateInstance(listType);
199+
200+
foreach (var childToken in token.Children())
201+
{
202+
var typeName = GetTypeNameFromToken(childToken);
203+
if (string.IsNullOrEmpty(typeName))
204+
{
205+
var item = childToken.ToObject(type);
206+
listType
207+
.GetRuntimeMethod(nameof(List<object>.Add), new[] { type })
208+
.Invoke(list, new object[] { item });
209+
}
210+
else
211+
{
212+
var builtType = Type.GetType($"{NamespacePrefix}{typeName}");
213+
if (builtType != null && GetTypeHierarchy(builtType).Any(x => x == type))
214+
{
215+
var child = (Thing)childToken.ToObject(builtType);
216+
listType
217+
.GetRuntimeMethod(nameof(List<object>.Add), new[] { type })
218+
.Invoke(list, new object[] { child });
219+
}
220+
}
221+
}
222+
223+
return list;
224+
}
225+
226+
private static IEnumerable<Type> GetTypeHierarchy(Type type)
227+
{
228+
if (type == null)
229+
{
230+
yield break;
231+
}
232+
233+
yield return type;
234+
235+
var baseType = type.GetTypeInfo().BaseType;
236+
while (baseType != null)
237+
{
238+
yield return baseType;
239+
baseType = baseType.GetTypeInfo().BaseType;
240+
}
241+
}
242+
216243
private static object SanitizeReaderValue(JsonReader reader, JsonToken tokenType) =>
217244
tokenType == JsonToken.Integer ? Convert.ToInt32(reader.Value) : reader.Value;
218245

Tests/Schema.NET.Test/BookTest.cs

Lines changed: 70 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -18,66 +18,66 @@ public class BookTest
1818
},
1919
Url = new Uri("http://www.barnesandnoble.com/store/info/offer/JDSalinger"),
2020
WorkExample = new List<CreativeWork>()
21+
{
22+
new Book()
2123
{
22-
new Book()
24+
Isbn = "031676948",
25+
BookEdition = "2nd Edition",
26+
BookFormat = BookFormatType.Hardcover,
27+
PotentialAction = new ReadAction()
2328
{
24-
Isbn = "031676948",
25-
BookEdition = "2nd Edition",
26-
BookFormat = BookFormatType.Hardcover,
27-
PotentialAction = new ReadAction()
29+
Target = new EntryPoint()
2830
{
29-
Target = new EntryPoint()
30-
{
31-
UrlTemplate = "http://www.barnesandnoble.com/store/info/offer/0316769487?purchase=true",
32-
ActionPlatform = new List<Uri>()
33-
{
34-
new Uri("http://schema.org/DesktopWebPlatform"),
35-
new Uri("http://schema.org/IOSPlatform"),
36-
new Uri("http://schema.org/AndroidPlatform")
37-
}
38-
},
39-
ExpectsAcceptanceOf = new Offer()
31+
UrlTemplate = "http://www.barnesandnoble.com/store/info/offer/0316769487?purchase=true",
32+
ActionPlatform = new List<Uri>()
4033
{
41-
Price = 6.99M,
42-
PriceCurrency = "USD",
43-
EligibleRegion = new Country()
44-
{
45-
Name = "US"
46-
},
47-
Availability = ItemAvailability.InStock
34+
new Uri("http://schema.org/DesktopWebPlatform"),
35+
new Uri("http://schema.org/IOSPlatform"),
36+
new Uri("http://schema.org/AndroidPlatform")
4837
}
4938
},
50-
},
51-
new Book()
52-
{
53-
Isbn = "031676947",
54-
BookEdition = "1st Edition",
55-
BookFormat = BookFormatType.EBook,
56-
PotentialAction = new ReadAction()
39+
ExpectsAcceptanceOf = new Offer()
5740
{
58-
Target = new EntryPoint()
41+
Price = 6.99M,
42+
PriceCurrency = "USD",
43+
EligibleRegion = new Country()
5944
{
60-
UrlTemplate = "http://www.barnesandnoble.com/store/info/offer/031676947?purchase=true",
61-
ActionPlatform = new List<Uri>()
62-
{
63-
new Uri("http://schema.org/DesktopWebPlatform"),
64-
new Uri("http://schema.org/IOSPlatform"),
65-
new Uri("http://schema.org/AndroidPlatform")
66-
}
45+
Name = "US"
6746
},
68-
ExpectsAcceptanceOf = new Offer()
47+
Availability = ItemAvailability.InStock
48+
}
49+
},
50+
},
51+
new Book()
52+
{
53+
Isbn = "031676947",
54+
BookEdition = "1st Edition",
55+
BookFormat = BookFormatType.EBook,
56+
PotentialAction = new ReadAction()
57+
{
58+
Target = new EntryPoint()
59+
{
60+
UrlTemplate = "http://www.barnesandnoble.com/store/info/offer/031676947?purchase=true",
61+
ActionPlatform = new List<Uri>()
6962
{
70-
Price = 1.99M,
71-
PriceCurrency = "USD",
72-
EligibleRegion = new Country()
73-
{
74-
Name = "UK"
75-
},
76-
Availability = ItemAvailability.InStock
63+
new Uri("http://schema.org/DesktopWebPlatform"),
64+
new Uri("http://schema.org/IOSPlatform"),
65+
new Uri("http://schema.org/AndroidPlatform")
7766
}
7867
},
79-
}
68+
ExpectsAcceptanceOf = new Offer()
69+
{
70+
Price = 1.99M,
71+
PriceCurrency = "USD",
72+
EligibleRegion = new Country()
73+
{
74+
Name = "UK"
75+
},
76+
Availability = ItemAvailability.InStock
77+
}
78+
},
8079
}
80+
}
8181
};
8282

8383
private readonly string json =
@@ -158,5 +158,28 @@ public void ToString_BookGoogleStructuredData_ReturnsExpectedJsonLd() =>
158158
[Fact]
159159
public void Deserializing_BookJsonLd_ReturnsBook() =>
160160
Assert.Equal(this.book.ToString(), JsonConvert.DeserializeObject<Book>(this.json).ToString());
161+
162+
[Fact]
163+
public void Deserializing_HasPersonAsAuthor_OrganizationIsNullAndHasPerson()
164+
{
165+
var json =
166+
"{" +
167+
"\"@context\" : \"http://schema.org\"," +
168+
"\"@type\" : \"Book\"," +
169+
"\"author\" : [" +
170+
"{" +
171+
"\"@type\" : \"Person\"," +
172+
"\"name\" : \"NameOfPerson1\"," +
173+
"}," +
174+
"]," +
175+
"\"typicalAgeRange\" : \"14\"," +
176+
"\"isbn\" : \"3333\"" +
177+
"}";
178+
var book = JsonConvert.DeserializeObject<Book>(json);
179+
180+
Assert.Equal(0, book.Author.Value.Value1.Count);
181+
var person = Assert.Single(book.Author.Value.Value2);
182+
Assert.Equal("NameOfPerson1", person.Name);
183+
}
161184
}
162185
}

0 commit comments

Comments
 (0)