Serializing with JSON
Opened this issue · 4 comments
Hi, I was wondering if anyone had any thoughts about serializing with JSON instead of BinaryFormatter. I implemented the following as a test on my local dev and it seems to work well:
https://patrickdesjardins.com/blog/serializing-complex-object-for-redis
PROS
- The big PRO is that you don't have to add and maintain [Serializable] to all your classes being cached in Redis.
CONS - Small size increase, could compress but obviously adds overhead
- It won't honor [NonSerialized] attributes, but I guess it would honor [JsonIgnore] attributes
- It could be potentially easier for someone to inject a "Bad" object in the cache since the type is included in the cached object.
Here is an example of a cached item...
get dma9_DNN_SkinDefaults_SkinInfo
"{\r\n "$id": "1",\r\n "$type": "DotNetNuke.UI.Skins.SkinDefaults, DotNetNuke",\r\n "AdminDefaultName": "Admin.ascx",\r\n "DefaultName": "Inner.ascx",\r\n "Folder": "/Xcillion/"\r\n}"
Just curious if anyone has any thoughts on this or have tried this with DNN. Thanks
Sounds really interesting to me. When I built this module some time back, I tried with different serializers like DataContract, XmlSerializer (there is still code about it
that is not currently in use), etc. After lot of tests, the I got the best performance with binary uncompressed. Note that there is already an option to compress/decompress in place.At that time, I didn't try with any JSON serialization, and after reviewing this post (https://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/), I'm thinking that having the option to use JSON or even other serializers would be an interesting experiment. Seems that just with JSON the performance would be better than binary.
Do you have measured the performance with lot of objects (small and large) so we can do some type of comparison?
On the other hand, the binary serializer can even serialize/deserialize private properties, not sure if that's possible with the other ones.
Just to give an update on this. Everything was looking good, I was getting really good results on size and time, but then I hit a roadblock. I get the following exception:
Exception of type 'DotNetNuke.Collections.Internal.ReadLockRequiredException' was thrown.
at DotNetNuke.Collections.Internal.SharedDictionary2.EnsureReadAccess() at DotNetNuke.Collections.Internal.SharedDictionary
2.IEnumerable_GetEnumerator()
at Newtonsoft.Json.Utilities.DictionaryWrapper`2.System.Collections.IDictionary.GetEnumerator()
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer)
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Formatting formatting, JsonSerializerSettings settings)
at DotNetNuke.Providers.RedisCachingProvider.Shared.SerializeJSON(Object source) in C:\dnnsites\ot9\Providers\CachingProviders\RedisCachingProvider\RedisCachingProvider\Shared.cs:line 110
at DotNetNuke.Providers.RedisCachingProvider.RedisCachingProvider.Insert(String key, Object value, DNNCacheDependency dependency, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback) in C:\dnnsites\ot9\Providers\CachingProviders\RedisCachingProvider\RedisCachingProvider\RedisCachingProvider.cs:line 205
This occurs when TabInfo is serialized. What is specifically causing it is the following member variables:
In order for those elements to be accessed, it needs to be accessed as follows, or you can't read the element.
Not sure if anyone has any ideas.... Thanks
Was any progress on this ever made?
I am going to take a slightly different approach here. If the JSON serialization fails for some reason I am going to fall back to Binary serialization. Then check for base64encoded strings during deserialization.