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.
ToList() on the offending enumerables,
DeserializeObject work as expected.
Phew, that wasn't nearly as bad as I thought it would be.