When serializing using the Newtonsoft.Json library, we can specify a custom ContractResolver to e.g. make the properties appear to have a different name. We can use this possibility to shorten the key names.
Important note: although there can be some specific circumstances when the method described below is suitable, there are many better methods how to reduce JSON size.
Firstly, some test classes:
And a test object we will serialize:
When serializing it using the default method:
We will get:
When replacing the key names, we will get a shorter output:
Of course, we have to actually store the original key names to be able to deserialize it again. The key names are listed at the end (after the semicolon). The first key listed here is always translated to A, the second to B, etc. - so the mapping is implicitly defined by the position in the list.
The implementation:
And usage:
This approach worked well on the test data presented at the beginning, mainly because:
the data contained an array with a considerable count of objects, so the same property names were repeated more times (so e.g. for shortening 10 occurrences of the same property name we only had to write the original long name once to the mapping list at the end)
the values were quite short, so the key names took a considerable amount of space in the whole serialized JSON
Note that the mapping is global for the whole JSON, not only for each specific array. If the same property name appears in some other part of the JSON, the same mapping is used (the name will still appear only once in the mapping list at the end).
When using the implementation of CompressingSerialization, be sure to measure the performance to see if it is suitable for your task. I took a quick lame performance measurement and discovered that it is a lot slower than only using SerializeObject and DeserializeObject. This is mainly because for each usage, a new CustomDataContractResolver is created, so type information in DefaultContractResolver (which is normally cached globally) has to be re-built every time.
Some considerations about how to improve the performance:
always re-use the same DefaultContractResolver somehow
cache the short property names (at least the most used ones, e.g. “A” to “Z”) to skip creating StringBuilder to always build a new string with only one character
One more problem: in the example above, it registered even the property name Details (it looks like CreateProperty is called for it), even though this property is marked with JsonIgnore and thus never actually used.
Additionally, here is an alternative CompressingSerialization using custom JsonConverter instead of a custom ContractResolver.
This implementation is more complicated and it is incomplete (e.g. does not handle all TokenTypes). But it is a good example to demonstrate another way how to influence the behavior of the Newtonsoft.Json library - by overriding another part of the processing.