Simple serialize of encoding
My problem was the serialize of the Encoding . Let’s suppose that we have a class that have a property Encoding( maybe to read a file ).
internal class MyTest { public MyTest() { enc = ASCIIEncoding.ASCII; } public Encoding enc { get; set; } }
We want to serialize this class in order to let the administrator/people to decide what will be the encoding.
When we serialize( obvious, with NewtonSoftJson) , we obtain this kind of data:
{
“enc”: {
“IsSingleByte”: true,
“BodyName”: “us-ascii”,
“EncodingName”: “US-ASCII”,
“HeaderName”: “us-ascii”,
“WebName“: “us-ascii”,
“WindowsCodePage”: 1252,
“IsBrowserDisplay”: false,
“IsBrowserSave”: false,
“IsMailNewsDisplay”: true,
“IsMailNewsSave”: true,
“EncoderFallback”: {
“DefaultString”: “?”,
“MaxCharCount”: 1
},
“DecoderFallback”: {
“DefaultString”: “?”,
“MaxCharCount”: 1
},
“IsReadOnly”: true,
“CodePage”: 20127
}
}
This is too much for someone to edit . We want a simple string that can be edited easy – and the WebName , that is , in fact , a string from https://www.iana.org/assignments/character-sets/character-sets.xhtml seems the obvious choice.
So – I have done a JSONConverter class just for this property. It is very simple:
public class JsonEncodingConverter : JsonConverter { public override bool CanConvert(Type objectType) { return (typeof(Encoding).IsAssignableFrom(objectType)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { string webName = ""; if (reader.TokenType == JsonToken.String) { webName = reader.Value?.ToString(); } existingValue = Encoding.GetEncoding(webName); return existingValue; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { string webName = (value as Encoding).WebName; serializer.Serialize(writer, webName); } }
And can be used very easy:
MyTest m = new MyTest(); JsonEncodingConverter[] conv = new[] { new JsonEncodingConverter() }; string original = JsonConvert.SerializeObject(m, Formatting.Indented); string data = JsonConvert.SerializeObject(m, Formatting.Indented, conv); //https://www.iana.org/assignments/character-sets/character-sets.xhtml Console.WriteLine(data); Console.WriteLine("and now the original"); Console.WriteLine(original); MyTest s = JsonConvert.DeserializeObject<MyTest>(data, conv); Console.WriteLine(s.enc.WebName);
The result of serializing it is now
{
“enc”: “us-ascii”
}
And because it has this code
public override bool CanConvert(Type objectType) { return (typeof(Encoding).IsAssignableFrom(objectType)); }
it means it will serialize just the encoding, not other tools.
And it is more easy to be edited by someone.
Moral: Aim for simple string that can be edited can be achieved when serializing. Do not stay with defaults!
( you can easy achieve backwards compatibility for already serialized Encoding by asking
if (reader.TokenType == JsonToken.StartObject) { webName = reader.Value?.ToString(); //handling old data format for encoding while (reader.TokenType != JsonToken.EndObject) { if (!reader.Read()) break; if (reader.TokenType != JsonToken.PropertyName) continue; var val = reader.Value?.ToString(); if (string.Compare("webname", val, StringComparison.InvariantCultureIgnoreCase) == 0) { webName = reader.ReadAsString(); //do not break - advance reading to the end //break; } } }
)