UPDATE Found the issue -- was inheriting from wrong class, needed to be JsonConverter.
I have a class that has a Location property of type System.Data.Entity.Spatial.DbGeography. The default Json.NET serializer puts out JSON text like this:
... "PlaceType": 0, "Location": { "Geography": { "CoordinateSystemId": 4326, "WellKnownText": "POINT (-88.00000 44.00000)" } }, "AddedDT": null, ...
I want it to put out text like this:
... "PlaceType": 0, "Location": [-88.00000,44.00000], "AddedDT": null, ...
...so it seems to me what I should do would be to override whatever converter is currently being used on the DbGeography type.
The examples I've seen so far that use CustomCreationConverters and ContractResolvers seem to address how you'd replace the serializer for the main class being serialized, not for a type that's only a property of that class. The examples that involve annotating the class that's being overridden don't work for me because I don't define DbGeography in my code and it's effectively a sealed class because it has no constructor and can only be instantiated by internal
factory methods.
Is there a way to apply a JsonConverter to a type fluently? If so, what would the converter look like? Do I just override the WriteJson() method?
Steps to follow the basic patternCreate a class that derives from JsonConverter<T> where T is the type to be serialized and deserialized. Override the Read method to deserialize the incoming JSON and convert it to type T . Use the Utf8JsonReader that's passed to the method to read the JSON.
JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object). If you serialize this result it will generate a text with the structure and the record returned.
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.
You can add a custom serializer to a single attribute like this:
public class Comment { public string Author { get; set; } [JsonConverter(typeof(NiceDateConverter))] public DateTime Date { get; set; } public string Text { get; set; } } public class NiceDateConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var date = (DateTime) value; var niceLookingDate = date.ToString("MMMM dd, yyyy 'at' H:mm tt"); writer.WriteValue(niceLookingDate); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter."); } public override bool CanRead { get { return false; } } public override bool CanConvert(Type objectType) { return objectType == typeof(DateTime); } }
Then, when you serialize your object with JsonConvert.SerializeObject(), the custom serializer will be used for the Date property.
Turns out I just needed to inherit from JsonConverter instead of CustomCreationConverter, and everything else I was trying to change was OK all along.
I'm still not sure if there's a way to apply the JsonConverter fluently, but there is another way to apply the JsonConverter without referencing Json.NET in your domain/core project or marking up your domain classes with references to a peripheral library:
var jsonSerializer = new JsonSerializer(); jsonSerializer.Converters.Add(new DbGeographyConverter()); jsonSerializer.Serialize(jsonWriter, place);
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