-
Notifications
You must be signed in to change notification settings - Fork 134
/
MapConverter.cs
60 lines (53 loc) · 2.4 KB
/
MapConverter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace GraphQL.Client.Serializer.Newtonsoft;
public class MapConverter : JsonConverter<Map>
{
public override void WriteJson(JsonWriter writer, Map value, JsonSerializer serializer) =>
throw new NotImplementedException(
"This converter currently is only intended to be used to read a JSON object into a strongly-typed representation.");
public override Map? ReadJson(JsonReader reader, Type objectType, Map existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var rootToken = JToken.ReadFrom(reader);
return rootToken.Type switch
{
JTokenType.Object => (Map)ReadDictionary(rootToken, new Map()),
JTokenType.Null => null,
_ => throw new ArgumentException("This converter can only parse when the root element is a JSON Object.")
};
}
private object? ReadToken(JToken? token) =>
token switch
{
JObject jObject => ReadDictionary(jObject, new Dictionary<string, object>()),
JArray jArray => ReadArray(jArray).ToList(),
JValue jValue => jValue.Value,
JConstructor _ => throw new ArgumentOutOfRangeException(nameof(token.Type),
"cannot deserialize a JSON constructor"),
JProperty _ => throw new ArgumentOutOfRangeException(nameof(token.Type),
"cannot deserialize a JSON property"),
JContainer _ => throw new ArgumentOutOfRangeException(nameof(token.Type),
"cannot deserialize a JSON comment"),
_ => throw new ArgumentOutOfRangeException(nameof(token.Type))
};
private Dictionary<string, object> ReadDictionary(JToken element, Dictionary<string, object> to)
{
foreach (var property in ((JObject)element).Properties())
{
if (IsUnsupportedJTokenType(property.Value.Type))
continue;
to[property.Name] = ReadToken(property.Value);
}
return to;
}
private IEnumerable<object?> ReadArray(JArray element)
{
foreach (var item in element)
{
if (IsUnsupportedJTokenType(item.Type))
continue;
yield return ReadToken(item);
}
}
private bool IsUnsupportedJTokenType(JTokenType type) => type == JTokenType.Constructor || type == JTokenType.Property || type == JTokenType.Comment;
}