public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // Instantiate the JSON converter var oktaConverter = new OktaJsonConverter(); // If we're deserializing a single object if (reader.TokenType == JsonToken.StartObject) { // Get the JSON for that object JObject jsonObject = JObject.Load(reader); // Find the properties that can't be deserialized by starting with all possible properties var unDeserializable = jsonObject.Properties().ToDictionary(x => (x as JProperty).Name.ToString(), y => y); // Start building our own object var newObject = Activator.CreateInstance(objectType); // Loop through all the properties of our desired type foreach (PropertyInfo p in objectType.GetProperties()) { // If member is serializable var jsonAttribute = System.Attribute.GetCustomAttribute(p, typeof(JsonPropertyAttribute)); if (jsonAttribute != null) { // Get the mapped attribute name for a field or property var attributeName = (jsonAttribute as JsonPropertyAttribute).PropertyName.ToString(); // Get the value from our jsonObject JProperty prop = jsonObject.Properties().FirstOrDefault(x => x.Name == attributeName); if (prop == null) { continue; } JToken value = prop.Value; // Convert the value to it's relevant type object v; // Handle the ApiObject case if (typeof(ApiObject).IsAssignableFrom(p.PropertyType)) { v = Utils.DeserializeObject(value.ToString(), p.PropertyType); } // Handle the Link dictionary case else if (typeof(Dictionary<string, List<Link>>).IsAssignableFrom(p.PropertyType)) { var linkDictionary = new Dictionary<string, List<Link>>(); // Loop through each of the named links foreach (JToken jt in value.Children()) { // Get the first value of the named link var linkJTokenName = ((JProperty)jt).Name; var linkJTokenValue = ((JProperty)jt).Value; // Deserialize that value into something we can use List<Link> linkList; if (linkJTokenValue.Type == JTokenType.Array) { linkList = Utils.Deserialize<List<Link>>(linkJTokenValue.ToString()); } else { var linkValue = Utils.Deserialize<Link>(linkJTokenValue.ToString()); linkList = new List<Link> { linkValue }; } // Add it to our dictionary linkDictionary.Add(linkJTokenName, linkList); } v = linkDictionary; } // Handle lists and objects else if (value.Type == JTokenType.Array || value.Type == JTokenType.Object) { v = Utils.DeserializeObject(value.ToString(), p.PropertyType); } // Handle everything else else { if (p.PropertyType == typeof(DateTime) && value.Type == JTokenType.Null || value.Type == JTokenType.None) { unDeserializable.Remove(attributeName); continue; } else { v = Convert.ChangeType(value, p.PropertyType, null); } } // Set the property on the object we're building p.SetValue(newObject, v, null); unDeserializable.Remove(attributeName); } } // Add all the properties that weren't serialized (newObject as ApiObject).UnmappedProperties = unDeserializable; return newObject; } // If we're deserializing an array else if (reader.TokenType == JsonToken.StartArray) { JToken jsonToken = JArray.ReadFrom(reader); List<JToken> jsonTokens = jsonToken.ToList(); var resultObjects = new List<ApiObject>(); foreach (JToken arrayToken in jsonTokens) { ApiObject resultElement = Utils.DeserializeObject( arrayToken.ToString(), objectType) as ApiObject; resultObjects.Add(resultElement); } return resultObjects; } throw new NotImplementedException("Can't deserialize"); }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // Instantiate the JSON converter var oktaConverter = new OktaJsonConverter(); // If we're deserializing a single object if (reader.TokenType == JsonToken.StartObject) { // Get the JSON for that object JObject jsonObject = JObject.Load(reader); // Find the properties that can't be deserialized by starting with all possible properties var unDeserializable = jsonObject.Properties().ToDictionary(x => (x as JProperty).Name.ToString(), y => y); // Start building our own object var newObject = Activator.CreateInstance(objectType); // Loop through all the properties of our desired type foreach (PropertyInfo p in objectType.GetProperties()) { // If member is serializable var jsonAttribute = System.Attribute.GetCustomAttribute(p, typeof(JsonPropertyAttribute)); if (jsonAttribute != null) { // Get the mapped attribute name for a field or property var attributeName = (jsonAttribute as JsonPropertyAttribute).PropertyName.ToString(); // Get the value from our jsonObject JProperty prop = jsonObject.Properties().FirstOrDefault(x => x.Name == attributeName); if (prop == null) { continue; } JToken value = prop.Value; // Convert the value to it's relevant type object v; // Handle the ApiObject case if (typeof(ApiObject).IsAssignableFrom(p.PropertyType)) { v = Utils.DeserializeObject(value.ToString(), p.PropertyType); } // Handle the Link dictionary case else if (typeof(Dictionary <string, List <Link> >).IsAssignableFrom(p.PropertyType)) { var linkDictionary = new Dictionary <string, List <Link> >(); // Loop through each of the named links foreach (JToken jt in value.Children()) { // Get the first value of the named link var linkJTokenName = ((JProperty)jt).Name; var linkJTokenValue = ((JProperty)jt).Value; // Deserialize that value into something we can use List <Link> linkList; if (linkJTokenValue.Type == JTokenType.Array) { linkList = Utils.Deserialize <List <Link> >(linkJTokenValue.ToString()); } else { var linkValue = Utils.Deserialize <Link>(linkJTokenValue.ToString()); linkList = new List <Link> { linkValue }; } // Add it to our dictionary linkDictionary.Add(linkJTokenName, linkList); } v = linkDictionary; } // Handle lists and objects else if (value.Type == JTokenType.Array || value.Type == JTokenType.Object) { v = Utils.DeserializeObject(value.ToString(), p.PropertyType); } // Handle everything else else { if (p.PropertyType == typeof(DateTime) && value.Type == JTokenType.Null || value.Type == JTokenType.None) { unDeserializable.Remove(attributeName); continue; } else { v = Convert.ChangeType(value, p.PropertyType, null); } } // Set the property on the object we're building p.SetValue(newObject, v, null); unDeserializable.Remove(attributeName); } } // Add all the properties that weren't serialized (newObject as ApiObject).UnmappedProperties = unDeserializable; return(newObject); } // If we're deserializing an array else if (reader.TokenType == JsonToken.StartArray) { JToken jsonToken = JArray.ReadFrom(reader); List <JToken> jsonTokens = jsonToken.ToList(); var resultObjects = new List <ApiObject>(); foreach (JToken arrayToken in jsonTokens) { ApiObject resultElement = Utils.DeserializeObject( arrayToken.ToString(), objectType) as ApiObject; resultObjects.Add(resultElement); } return(resultObjects); } throw new NotImplementedException("Can't deserialize"); }