Fixing Deferred Execution Serialization Issue
I stumbled upon an interesting problem today while working with a legacy Xamarin project. Surprisingly, the exception message wasn't entirely unhelpful:
Newtonsoft.Json.JsonSerializationException: Cannot create and populate list type System.Linq.Enumerable+SelectEnumerableIterator`2[System.Collections.Generic.KeyValuePair`2[System.String,System.String],System.String]
The first clue that something is amiss is the concrete type that Newtonsoft.Json
is attempting to deserialize: SelectEnumerableIterator
. This class is returned when calling Select()
on an enumerable. That seems to make sense, so why does it cause a problem?
Select
creates an enumerable that only evaluates the expression provided when values are required (such as calling ToList()
or performing a foreach
on it), utilising a technique known as deferred execution.
So, how do we avoid this particular exception? We make sure that any enumerables being passed to the serializer are not deferred, and all values are present.
After calling ToList()
on the offending enumerables, SerializeObject
and DeserializeObject
work as expected.
Phew, that wasn't nearly as bad as I thought it would be.