Skip to content

Commit eb9add7

Browse files
authored
Merge pull request #71 from candela-software/master
More on JSON serialization
2 parents 8ac0dde + b095f46 commit eb9add7

File tree

82 files changed

+446
-209
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+446
-209
lines changed

Source/Schema.NET/ValuesJsonConverter.cs

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
namespace Schema.NET
22
{
33
using System;
4+
using System.Collections;
45
using System.Collections.Generic;
56
using System.Diagnostics;
67
using System.Globalization;
@@ -63,6 +64,8 @@ public override object ReadJson(
6364
var value = reader.Value;
6465

6566
var token = JToken.Load(reader);
67+
var count = token.Children().Count();
68+
6669
#pragma warning disable CA1062 // Validate arguments of public methods
6770
if (mainType.GenericTypeArguments.Length == 1)
6871
#pragma warning restore CA1062 // Validate arguments of public methods
@@ -82,14 +85,29 @@ public override object ReadJson(
8285
{
8386
if (tokenType == JsonToken.StartArray)
8487
{
88+
var total = 0;
8589
var items = new List<object>();
86-
foreach (var type in mainType.GenericTypeArguments)
90+
for (var i = mainType.GenericTypeArguments.Length - 1; i >= 0; i--)
8791
{
92+
var type = mainType.GenericTypeArguments[i];
8893
var unwrappedType = type.GetUnderlyingTypeFromNullable();
89-
var args = ReadJsonArray(token, unwrappedType);
90-
var genericType = typeof(OneOrMany<>).MakeGenericType(type);
91-
var item = (IValues)Activator.CreateInstance(genericType, args);
92-
items.Add(item);
94+
// only read as many items as there are tokens left
95+
var args = ReadJsonArray(token, unwrappedType, count - total);
96+
97+
if (args != null && args.Count > 0)
98+
{
99+
var genericType = typeof(OneOrMany<>).MakeGenericType(type);
100+
var item = (IValues)Activator.CreateInstance(genericType, args);
101+
items.Add(item);
102+
103+
total += args.Count;
104+
105+
if (total >= count)
106+
{
107+
// if we have deserialized enough items as there are tokens, break
108+
break;
109+
}
110+
}
93111
}
94112

95113
argument = items;
@@ -99,11 +117,10 @@ public override object ReadJson(
99117
for (var i = mainType.GenericTypeArguments.Length - 1; i >= 0; i--)
100118
{
101119
var type = mainType.GenericTypeArguments[i];
102-
object args = null;
103120

104121
try
105122
{
106-
args = ParseTokenArguments(token, tokenType, type, value);
123+
var args = ParseTokenArguments(token, tokenType, type, value);
107124

108125
if (args != null)
109126
{
@@ -209,7 +226,7 @@ private static object ParseTokenArguments(JToken token, JsonToken tokenType, Typ
209226
{
210227
const string SCHEMA_ORG = "http://schema.org/";
211228
const int SCHEMA_ORG_LENGTH = 18; // equivalent to "http://schema.org/".Length
212-
object args = null;
229+
object args;
213230
var unwrappedType = type.GetUnderlyingTypeFromNullable();
214231
if (unwrappedType.GetTypeInfo().IsEnum)
215232
{
@@ -434,53 +451,58 @@ private static Type ToClass(Type type)
434451
return type;
435452
}
436453

437-
private static object ReadJsonArray(JToken token, Type type)
454+
private static IList ReadJsonArray(JToken token, Type type, int? count = null)
438455
{
439456
var classType = ToClass(type);
440-
var listType = typeof(List<>).MakeGenericType(classType);
457+
var listType = typeof(List<>).MakeGenericType(type); // always read into list of interfaces
441458
var list = Activator.CreateInstance(listType);
459+
var i = 0;
460+
461+
if (count == null)
462+
{
463+
// if maximum item count not assigned, set to count of child tokens
464+
count = token.Children().Count();
465+
}
442466

443467
foreach (var childToken in token.Children())
444468
{
445469
var typeName = GetTypeNameFromToken(childToken);
446470
if (string.IsNullOrEmpty(typeName))
447471
{
448-
var item = childToken.ToObject(classType);
449-
listType
450-
.GetRuntimeMethod(nameof(List<object>.Add), new[] { classType })
451-
.Invoke(list, new object[] { item });
472+
var child = childToken.ToObject(classType);
473+
var method = listType.GetRuntimeMethod(nameof(List<object>.Add), new[] { classType });
474+
475+
if (method != null)
476+
{
477+
method.Invoke(list, new object[] { child });
478+
479+
i++;
480+
}
452481
}
453482
else
454483
{
455484
var builtType = Type.GetType($"{NamespacePrefix}{typeName}");
456-
if (builtType != null && GetTypeHierarchy(builtType).Any(x => x == classType))
485+
if (builtType != null && type.GetTypeInfo().IsAssignableFrom(builtType.GetTypeInfo()))
457486
{
458487
var child = (Thing)childToken.ToObject(builtType);
459-
listType
460-
.GetRuntimeMethod(nameof(List<object>.Add), new[] { classType })
461-
.Invoke(list, new object[] { child });
488+
var method = listType.GetRuntimeMethod(nameof(List<object>.Add), new[] { classType });
489+
490+
if (method != null)
491+
{
492+
method.Invoke(list, new object[] { child });
493+
494+
i++;
495+
}
462496
}
463497
}
464-
}
465-
466-
return list;
467-
}
468498

469-
private static IEnumerable<Type> GetTypeHierarchy(Type type)
470-
{
471-
if (type == null)
472-
{
473-
yield break;
499+
if (i == count)
500+
{
501+
break;
502+
}
474503
}
475504

476-
yield return type;
477-
478-
var baseType = type.GetTypeInfo().BaseType;
479-
while (baseType != null)
480-
{
481-
yield return baseType;
482-
baseType = baseType.GetTypeInfo().BaseType;
483-
}
505+
return (IList)list;
484506
}
485507

486508
private static string GetTypeNameFromToken(JToken token)

Source/Schema.NET/core/ItemList.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace Schema.NET
1+
namespace Schema.NET
22
{
33
using System;
44
using System.Runtime.Serialization;

Source/Schema.NET/core/combined/CreativeWorkAndItemListAndListItem.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace Schema.NET
1+
namespace Schema.NET
22
{
33
using System;
44
using System.Runtime.Serialization;

Source/Schema.NET/core/enumerations/ActionStatusType.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
namespace Schema.NET
1+
namespace Schema.NET
22
{
33
using System.Runtime.Serialization;
4+
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Converters;
46

57
/// <summary>
68
/// The status of an Action.
79
/// </summary>
10+
[JsonConverter(typeof(StringEnumConverter))]
811
public enum ActionStatusType
912
{
1013
/// <summary>

Source/Schema.NET/core/enumerations/BedType.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
namespace Schema.NET
1+
namespace Schema.NET
22
{
33
using System.Runtime.Serialization;
4+
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Converters;
46

57
/// <summary>
68
/// A type of bed. This is used for indicating the bed or beds available in an accommodation.
79
/// </summary>
10+
[JsonConverter(typeof(StringEnumConverter))]
811
public enum BedType
912
{
1013
}

Source/Schema.NET/core/enumerations/BoardingPolicyType.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
namespace Schema.NET
1+
namespace Schema.NET
22
{
33
using System.Runtime.Serialization;
4+
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Converters;
46

57
/// <summary>
68
/// A type of boarding policy used by an airline.
79
/// </summary>
10+
[JsonConverter(typeof(StringEnumConverter))]
811
public enum BoardingPolicyType
912
{
1013
/// <summary>

Source/Schema.NET/core/enumerations/BookFormatType.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
namespace Schema.NET
1+
namespace Schema.NET
22
{
33
using System.Runtime.Serialization;
4+
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Converters;
46

57
/// <summary>
68
/// The publication format of the book.
79
/// </summary>
10+
[JsonConverter(typeof(StringEnumConverter))]
811
public enum BookFormatType
912
{
1013
/// <summary>

Source/Schema.NET/core/enumerations/BusinessEntityType.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
namespace Schema.NET
1+
namespace Schema.NET
22
{
33
using System.Runtime.Serialization;
4+
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Converters;
46

57
/// <summary>
68
/// A business entity type is a conceptual entity representing the legal form, the size, the main line of business, the position in the value chain, or any combination thereof, of an organization or business person.&lt;br/&gt;&lt;br/&gt;
@@ -12,6 +14,7 @@
1214
/// &lt;li&gt;http://purl.org/goodrelations/v1#Reseller&lt;/li&gt;
1315
/// &lt;/ul&gt;
1416
/// </summary>
17+
[JsonConverter(typeof(StringEnumConverter))]
1518
public enum BusinessEntityType
1619
{
1720
}

Source/Schema.NET/core/enumerations/BusinessFunction.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
namespace Schema.NET
1+
namespace Schema.NET
22
{
33
using System.Runtime.Serialization;
4+
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Converters;
46

57
/// <summary>
68
/// The business function specifies the type of activity or access (i.e., the bundle of rights) offered by the organization or business person through the offer. Typical are sell, rental or lease, maintenance or repair, manufacture / produce, recycle / dispose, engineering / construction, or installation. Proprietary specifications of access rights are also instances of this class.&lt;br/&gt;&lt;br/&gt;
@@ -16,6 +18,7 @@
1618
/// &lt;li&gt;http://purl.org/goodrelations/v1#Buy&lt;/li&gt;
1719
/// &lt;/ul&gt;
1820
/// </summary>
21+
[JsonConverter(typeof(StringEnumConverter))]
1922
public enum BusinessFunction
2023
{
2124
}

Source/Schema.NET/core/enumerations/ContactPointOption.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
namespace Schema.NET
1+
namespace Schema.NET
22
{
33
using System.Runtime.Serialization;
4+
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Converters;
46

57
/// <summary>
68
/// Enumerated options related to a ContactPoint.
79
/// </summary>
10+
[JsonConverter(typeof(StringEnumConverter))]
811
public enum ContactPointOption
912
{
1013
/// <summary>

0 commit comments

Comments
 (0)