public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // Newtonsoft doesn't call CanConvert if you specify the converter using a JsonConverter attribute // they just assume you know what you're doing :) if (!CanConvert(objectType)) { // if there's no Unknown value, fall back to the StringEnumConverter behavior return(base.ReadJson(reader, objectType, existingValue, serializer)); } if (reader.TokenType == JsonToken.Integer) { var intValue = Convert.ToInt32(reader.Value); var values = (int[])Enum.GetValues(objectType); if (values.Contains(intValue)) { return(Enum.Parse(objectType, intValue.ToString())); } } if (reader.TokenType == JsonToken.String) { var stringValue = reader.Value.ToString(); return(UnknownEnum.Parse(objectType, stringValue)); } // we know there's an Unknown value because CanConvert returned true return(Enum.Parse(objectType, UnknownName)); }
public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType != JsonToken.StartObject) { return(null); } var contract = serializer.ContractResolver.ResolveContract(objectType) as JsonObjectContract; if (contract == null) { return(existingValue); } // if objectType is one of our known types, we can ignore the type property T targetObject = Create(objectType); // read the data into a JObject so we can look at it var value = JObject.Load(reader); if (targetObject == null) { // use the Type property var typeProperty = contract.Properties.GetClosestMatchProperty("Type"); if (typeProperty == null) { // we don't know the type. just bail return(existingValue); } if (!value.TryGetValue(typeProperty.PropertyName, StringComparison.OrdinalIgnoreCase, out var typeValue)) { // a type property exists on the contract, but the JObject has no value for it return(existingValue); } var type = UnknownEnum.Parse <ArtifactType>(typeValue.ToString()); targetObject = Create(type); } if (targetObject != null) { using (var objectReader = value.CreateReader()) { serializer.Populate(objectReader, targetObject); } } return(targetObject); }