I have a JsonConverter for my class DataType. I would like to do some special handling when plain string used in Json as the value of a property of type DataType. In the case where the value is a "full" object, I would like to do the "normal" deserialization.
Here is my attempt
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value != null && reader.ValueType == typeof (string))
{
return someSpecialDataTypeInstance;
}
else if (reader.TokenType == JsonToken.StartObject)
{
DataType dataType = serializer.Deserialize<DataType>(reader);
return dataType;
}
else
{
throw new JsonSerializationException();
}
}
But this doesn't work, because this line: DataType dataType = serializer.Deserialize(reader); causes infinite recursion.
Could this be done somehow easily? (without the need to manually go property-by-property)
JsonPropertyAttribute indicates that a property should be serialized when member serialization is set to opt-in. It includes non-public properties in serialization and deserialization. It can be used to customize type name, reference, null, and default value handling for the property value.
To ignore individual properties, use the [JsonIgnore] attribute.
DeserializeObject<T>(String,JsonConverter[]) Deserializes the JSON to the specified . NET type using a collection of JsonConverter. DeserializeObject(String, JsonSerializerSettings) Deserializes the JSON to a .
One easy way to do it is to allocate an instance of your class then use JsonSerializer.Populate(JsonReader, Object). This is the way it is done in the standard CustomCreationConverter<T>:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value != null && reader.ValueType == typeof(string))
{
return someSpecialDataTypeInstance;
}
else if (reader.TokenType == JsonToken.StartObject)
{
existingValue = existingValue ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
serializer.Populate(reader, existingValue);
return existingValue;
}
else if (reader.TokenType == JsonToken.Null)
{
return null;
}
else
{
throw new JsonSerializationException();
}
}
Limitations:
This does not handle situations when TypeNameHandling has been enabled and a "$type" property is present specifying a polymorphic subtype.
In this case you'll need to do some of the tricks use by JsonDerivedTypeConverer<T> in JsonConverter with Interface.
The type to be deserialized must have a parameterless constructor accessible to Json.NET. If not, and existingValue is null, it will be necessary to construct it manually, via new DataType(arg1, arg2, ...).
Reference preservation via PreserveReferencesHandling is not supported.
For one approach to handle this situation see How can I choose what type to deserialize at runtime based on the structure of the json?.
Sample fiddle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With