We’re experiencing an issue in Unity3D using C# and JsonFX on certain Android devices (Nexus 10, Galaxy Note 3 (SM-N9005, SM-N9000Q), Galaxy Tab, S4 (SGH-I337, SGH-M919, GT-I9505), Galaxy Note 10.1 (SM-P600, SM-P601), HTC One).

At the start of our App any Dictionary< string, string > serialized using JsonFX will correctly produce a string, but at some point becomes broken, and from then on will throw a JsonSerializationException with the following message:

Error JsonSerializationException: Types which implement Generic IDictionary<TKey, TValue> must have an IEnumerator which implements IDictionaryEnumerator. (System.Collections.Generic.Dictionary`2[System.String,System.String])

After investigation we have discovered that before some unknown event the following code (which is a simplification of the JsonFX Dictionary flow)...

var myDictionary = new Dictionary<string, string> {
    { "key1", "value1" },
    { "key2", "value2" },
};
IEnumerator enumerator = ((IEnumerable)((IDictionary)myDictionary)).GetEnumerator();
IDictionaryEnumerator dictionaryEnumerator = enumerator as IDictionaryEnumerator;

...successfully gets a dictionary enumerator of the type:

System.Collections.Generic.Dictionary`2+Enumerator[[System.String, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Dict Enumerator Path 1 = System.Collections.Generic.Dictionary`2+Enumerator[[System.String, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]

Once broken it instead fails to get a dictionary enumerator, because the enumerator which is returned is of the type:

System.Collections.Generic.Dictionary`2+KeyCollection[System.String,System.String]

Interestingly we've tried constructing a dictionary at the start and retesting the same instance through our game flow and even in this case it stops being serializable after the bug occurs.

Notably this only breaks for Dictionary< string, string > - we’re running the same tests with Dictionary< string, object > and they continue returning the expected enumerator types. Despite littering tests and logging throughout our game flow we haven’t been able to pin down exactly where this becomes broken, as it appears to break between updates of a coroutine.

We've tried dumping the loaded Assemblies before and after the bug to try and catch a dependency changing version but there are no differences.

This issue has been introduced by a innocent looking data only change which improves our Japanese character support so we suspect its exposing an existing issue.

We have trivially solve the issue by fixing the Json library’s dictionary parsing to support this new case but we’re more worried about what is causing this underlying issue, and what other issues it might be causing which we haven’t noticed yet.

Any one seen similar issues in the way Dictionary's or other collection classes behaviours changed like this, or have suggestions as to how we can further track down what is causing the issue?

1

There are 1 best solutions below

0
On

There are lots of problems when it comes to IEnumerator with MonoBehaviour. I have run at lease 10 of them in my entire career in our company.

It will either throw you and Object Exception. System. blah blah blah. But the point is, The MonoBehaviour Class. Does not have the Add Function to many of its Classes. That is why you're getting this error.

The first aid that we did is to Separate the class with an IEnumerator class that inherits with MonoBehaviour.

If MonoBehaviour instantiates the class with IEnumerator. Your bound to have this problem.

Now be fore you can test if this is the real problem. Try unhinretting MonoBehaviour and you will see that there is no error about IEnumerator. Ofcourse you will have an error about GameObject and such. But this is just to understand the problem.

Next, since IEnumerator is some what a problem for MonoBehaviour or List,Dictionary or any GenericType that have Add calls to them.

We decided to make it an Array instead. Specially in XML Deserializing and jSon calls.

This answer is just an extension of what causes the problem, but to fix your problem. You either need to avoid your deserializing, IEnumerator out of the MonoBehaviour class Inheritance. Or consider using Array that doesn't have Add() calls to it.