neuecc / Utf8Json

Definitely Fastest and Zero Allocation JSON Serializer for C#(NET, .NET Core, Unity, Xamarin).
MIT License
2.35k stars 266 forks source link

Issues using dynamic or Dictionary on iOS - NotSupportedException: System.AppDomain::DefineDynamicAssembly #173

Open colinmacleod opened 4 years ago

colinmacleod commented 4 years ago

I have an implementation that works fine on Unity Editor (macOS) but I am having trouble getting the same code to work on iOS.

The code does not use any class conversion at all - I’m only using dynamics or Dictionary conversion.

My first attempt to implement uses JsonSerializer.Deserialize(myJsonString) and JsonSerializer.ToJsonString(myDynamic).

When I deploy to iOS I get the following error:

NotSupportedException: System.AppDomain::DefineDynamicAssembly
  at System.AppDomain.DefineDynamicAssembly (System.Reflection.AssemblyName name, System.Reflection.Emit.AssemblyBuilderAccess access) [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Internal.Emit.DynamicAssembly..ctor (System.String moduleName) [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.Internal.DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateOriginal..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.DynamicObjectResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver+InnerResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.StandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.Awake () [0x00000] in <00000000000000000000000000000000>:0 
Rethrow as TypeInitializationException: The type initializer for 'Utf8Json.Resolvers.Internal.DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateOriginal' threw an exception.
  at Utf8Json.Resolvers.DynamicObjectResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver+InnerResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.StandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at .Awake () [0x00000] in <00000000000000000000000000000000>:0 
Rethrow as TypeInitializationException: The type initializer for 'Utf8Json.Resolvers.DynamicObjectResolver' threw an exception.
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver+InnerResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.StandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.Awake () [0x00000] in <00000000000000000000000000000000>:0 
Rethrow as TypeInitializationException: The type initializer for 'Utf8Json.Resolvers.Internal.DefaultStandardResolver.InnerResolver' threw an exception.
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.StandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.Awake () [0x00000] in <00000000000000000000000000000000>:0 
Rethrow as TypeInitializationException: The type initializer for 'Utf8Json.Resolvers.Internal.DefaultStandardResolver' threw an exception.
  at Utf8Json.Resolvers.StandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.Awake () [0x00000] in <00000000000000000000000000000000>:0 
Rethrow as TypeInitializationException: The type initializer for 'Utf8Json.Resolvers.StandardResolver' threw an exception.
  at Redacted.Awake () [0x00000] in <00000000000000000000000000000000>:0 

This happens on initialization at this point in an Awake method, the code is just the boilerplate copied from the docs:

Utf8Json.Resolvers.CompositeResolver.RegisterAndSetAsDefault(
    Utf8Json.Resolvers.GeneratedResolver.Instance,
    Utf8Json.Resolvers.StandardResolver.Default
);

If I remove that code from the Awake method, it fails on this line:

var json = JsonSerializer.Deserialize<dynamic>(resourceFile.text);

And this is the error message:

NotSupportedException: System.AppDomain::DefineDynamicAssembly
  at System.AppDomain.DefineDynamicAssembly (System.Reflection.AssemblyName name, System.Reflection.Emit.AssemblyBuilderAccess access) [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Internal.Emit.DynamicAssembly..ctor (System.String moduleName) [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.Internal.DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateOriginal..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.DynamicObjectResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver+InnerResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.StandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.JsonSerializer.get_DefaultResolver () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.JsonSerializer.Deserialize[T] (System.Byte[] bytes, System.Int32 offset, Utf8Json.IJsonFormatterResolver resolver) [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.InitializeCache () [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.Awake () [0x00000] in <00000000000000000000000000000000>:0 
Rethrow as TypeInitializationException: The type initializer for 'Utf8Json.Resolvers.Internal.DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateOriginal' threw an exception.
  at Utf8Json.Resolvers.DynamicObjectResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver+InnerResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.StandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.JsonSerializer.get_DefaultResolver () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.JsonSerializer.Deserialize[T] (System.Byte[] bytes, System.Int32 offset, Utf8Json.IJsonFormatterResolver resolver) [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.InitializeCache () [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.Awake () [0x00000] in <00000000000000000000000000000000>:0 
Rethrow as TypeInitializationException: The type initializer for 'Utf8Json.Resolvers.DynamicObjectResolver' threw an exception.
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver+InnerResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.StandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.JsonSerializer.get_DefaultResolver () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.JsonSerializer.Deserialize[T] (System.Byte[] bytes, System.Int32 offset, Utf8Json.IJsonFormatterResolver resolver) [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.InitializeCache () [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.Awake () [0x00000] in <00000000000000000000000000000000>:0 
Rethrow as TypeInitializationException: The type initializer for 'Utf8Json.Resolvers.Internal.DefaultStandardResolver.InnerResolver' threw an exception.
  at Utf8Json.Resolvers.Internal.DefaultStandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.Resolvers.StandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.JsonSerializer.get_DefaultResolver () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.JsonSerializer.Deserialize[T] (System.Byte[] bytes, System.Int32 offset, Utf8Json.IJsonFormatterResolver resolver) [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.InitializeCache () [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.Awake () [0x00000] in <00000000000000000000000000000000>:0 
Rethrow as TypeInitializationException: The type initializer for 'Utf8Json.Resolvers.Internal.DefaultStandardResolver' threw an exception.
  at Utf8Json.Resolvers.StandardResolver..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.JsonSerializer.get_DefaultResolver () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.JsonSerializer.Deserialize[T] (System.Byte[] bytes, System.Int32 offset, Utf8Json.IJsonFormatterResolver resolver) [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.InitializeCache () [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.Awake () [0x00000] in <00000000000000000000000000000000>:0 
Rethrow as TypeInitializationException: The type initializer for 'Utf8Json.Resolvers.StandardResolver' threw an exception.
  at Utf8Json.JsonSerializer.get_DefaultResolver () [0x00000] in <00000000000000000000000000000000>:0 
  at Utf8Json.JsonSerializer.Deserialize[T] (System.Byte[] bytes, System.Int32 offset, Utf8Json.IJsonFormatterResolver resolver) [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.InitializeCache () [0x00000] in <00000000000000000000000000000000>:0 
  at Redacted.Awake () [0x00000] in <00000000000000000000000000000000>:0 

Then I noticed this comment on the Unity documentation page https://docs.unity3d.com/Manual/iphone-unsupported.html:

Dynamic features like Duck Typing are not supported.

So, I reimplemented my code replacing every dynamic with Dictionary<string, object>. My code for the above line now looked like:

var json = JsonSerializer.Deserialize<Dictionary<string, object>>(resourceFile.text);

But the results were the same. The code did not work on iOS regardless. Again, it does work in Unity Editor with or without the startup code in Awake.

I tried running Utf8Json.UniversalCodeGenerator with various input files, but it didn’t seem to make any difference.

Not sure whether this is relevant, I am using Unity assembly definition files, and Utf8Json is in its own assembly with that name.

What am I missing?

@neuecc - I am sorry to raise this as an issue ticket. This is probably covered by the docs, but I could not work it out. I did spend several hours trying to get it to work and googling for a solution, before posting it up here.

I wasn't sure of the best way to contact you and I thought this might be useful to someone else!

colinmacleod commented 4 years ago

Hmm, my post seems to have swallowed the generics. The first part should read:

My first attempt to implement uses:

JsonSerializer.Deserialize<dynamic>(myJsonString) 

and

JsonSerializer.ToJsonString<dynamic>(myDynamic)
colinmacleod commented 4 years ago

@neuecc - could you please send a brief reply? if this is possible, I'd love you use Utf8Json

enue commented 4 years ago

How is this? https://github.com/neuecc/Utf8Json/issues/52

Utf8Json.Resolvers.CompositeResolver.RegisterAndSetAsDefault(
    new[] { PrimitiveObjectFormatter.Default },
    new[] { Utf8Json.Resolvers.GeneratedResolver.Instance, Utf8Json.Resolvers.BuiltinResolver.Instance });
enue commented 4 years ago

Initialization to use Dictionary conversion

Utf8Json.Resolvers.CompositeResolver.RegisterAndSetAsDefault(
    new[] { Utf8Json.Formatters.PrimitiveObjectFormatter.Default },
    new[] {
        Utf8Json.Resolvers.GeneratedResolver.Instance,
        Utf8Json.Resolvers.BuiltinResolver.Instance,
        Utf8Json.Resolvers.DynamicGenericResolver.Instance
    });

Unitypackage 1.3.7.1 doesn't contain this commit to fix a bug. https://github.com/neuecc/Utf8Json/commit/7f7d6e30b65e56e250baa49f5becba64730e5227