JSON .NET for Unity

JSON .NET for Unity is now only $20!
Serialization is integral to persisting data. This community has been extremely supportive of my asset and I wanted to return the favor by making sure it is affordable for everyone, so the price has been reduced on both FastSpring and the Asset Store.

My new JSON .NET Asset has been released.

With this release I bring JSON .NET to Unity 3.5+. While there have been other versions of JSON .NET floating around, they rely on older versions that will fail in Unity WebPlayer and will cause AOT errors in iOS. I’ve ported the JSON .NET library and removed those issues so it will now work on both WebPlayer and iOS. Find my asset here:

Product Site
On FastSpring
On the Asset Store

Highlights

  • Works in WebPlayer - Fixes KeyedCollection issues.
  • Works in iOS - No more AOT Errors from JSON .NET
  • Both JSON and BSON support have been ported
  • Retains most original JSON .NET namespaces
  • No DLL - This asset includes full source code

The fourth bullet above is notably the most important. There are other assets in the Asset Store that implement JSON .NET and do so with a compiled DLL. You can remove that DLL and add this Asset as an instant drop-in replacement. The asset also includes full source code, no compiled DLL.

I’ve also included a very rudimentary example scene. This includes a GameObject with an attached script that shows examples for serialization and deserialization for multiple scenarios (and gives examples of using both JSON and BSON).

The implementation is nearly identical to that of the original Newtonsoft library. There are two primary differences. I’ve removed dependencies on libraries that are not supported by Unity (such as System.Data).

UPDATE: Enums are now serialized to their Value by default. This is to stay consistent with the Newtonsoft implementation. You can serialize using a new EnumValueConverter which will serialize by value.

Or leave any feedback you’d like here.

Thanks!

~Dustin Horne

The new website is up.

I’ve launched a new website which I’ll be dedicating to my assets and Unity development. Here you will find more information about JSON .NET for Unity as well as other Unity related information in the future.

My Unity Website
http://unity.dustinhorne.com

JSON .NET for Unity Home Page
http://unity.dustinhorne.com/assets/json_net_unity

Any chance that you provide dlls for this as well?

Usually DLLs are provided and people are asking for source code.

This particular asset is made to import directly into Unity and work. In order to maintain cross-platform compatibility I can’t precompile it into a DLL. The framework differences are significant enough that the code requires precompiler directives to conditionally compile the correct version for different platforms. However, if you are only targeting iOS, you could download the asset, add it to a C# Class Library Project in Visual Studio and compile it yourself. You’d need to make sure you add the UNITY_IOS symbol in your build settings dialogue before compiling. You’d need to do this for UNITY_WEBPLAYER as well to target Unity WebPlayer. So you’d really need to build a separate assembly for the iOS, WebPlayer and desktop platforms. Otherwise, you can just import the asset as is and it will automatically compile to whatever your target platform is.

If you get the asset you’ll see conditionals like:

#if UNITY_IOS
...code here
#endif

I prefer it to get dlls and additionally to have the code within a Unity package. In 99% of the cases it is not necessary to see the source code and dlls reduces the compilation time a lot when the projects become heavier.
Are there many of those platform specific code sections? Are they somehow centralized or distributed through the whole code?

1 Like

The code base consists of somewhere around 192 files. There’s a tremendous number of conditionals and they’re pretty heavily distributed. They encompass a lot of platform specific code. Some of it is architectural differences and/or functionality that’s not available for iOS and some of it is security related in the way binding and security flags are set for reflection.

This is my first asset on the Asset Store. If you’re aware of a way to include the DLLs without them being automatically imported into the project itself I’d gladly add those as well. The problem is that I can’t include multiple DLLs with the exact same classes. But if I verified your invoice number I’d gladly compile the platform specific DLLs for you and send them over. It only takes a few minutes to do as I just need to set the appropriate symbols for each platform.

@Dustin Horne: Thanks for the answer! In that case it makes no sense to have dlls, as they are only useful if there is a way to just have one for all the platforms. I still consider to buy it.

Thanks Dantus! Yes, I wish there was a good clean way to make a single DLL that would work for all platforms. It may be possible but it would require stripping out a bunch of functionality and the only one I’m not sure I could workaround is the security flags for the reflection pieces which are necessary to ensure no dynamic code is used for iOS. If you have any other questions or need some assistance, definitely let me know.

Thanks,

~Dustin

I’ve started some usage documentation for JSON .NET in Unity. Here is my first blog post which demonstrates Serialization and Deserialization in both JSON and BSON format and discusses different use case scenarios:

http://www.dustinhorne.com/post/2013/09/25/Json-NET-for-Unity-Developers

Are there any particular scenarios that people would like to see demonstrated? My latest blog post shows basic implementation. I’m intending to demonstrate utilizing it with WWW to post data a web server and deserialize in my next article, but wanted to make sure I was covering topics that people were interested in.

Great work! But… there is some issues.

I try to make deserialization like this:

levelSettings = JsonConvert.DeserializeObject<Dictionary<string, LevelBase>>( levelSettingsFile.text, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto } );

Where LevelBase is base class for three other classes. In serialized string I have derived classes:

"1_1": {
    "$type": "LevelRegular, Assembly-CSharp",
    "moneyReward": 100,
    "resources": {
      "clover": 1
    },
    "id": "1_1",
    "duration": -1
  },
  "1_2": {
    "$type": "LevelRegular, Assembly-CSharp",
    "moneyReward": 800,
    "resources": {
      "clover": 3,
      "red_grape": 3
    },
    "id": "1_2",
    "duration": 150.0
  }
}

Aaaand when I run this code on iOS device, I get this:

(Filename: /Applications/buildAgent/work/cac08d8a5e25d4cb/Runtime/ExportGenerated/iPhonePlayer-armv7/UnityEngineDebug.cpp Line: 54)

ExecutionEngineException: Attempting to JIT compile method 'System.Collections.Generic.GenericEqualityComparer`1<Newtonsoft.Json.Serialization.DefaultSerializationBinder/TypeNameKey>:.ctor ()' while running with --aot-only.

  at System.Reflection.MonoCMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0 
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
  at System.Reflection.MonoCMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0 
  at System.Reflection.MonoCMethod.Invoke (BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0 
  at System.Reflection.ConstructorInfo.Invoke (System.Object[] parameters) [0x00000] in <filename unknown>:0 
  at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00000] in <filename unknown>:0 
  at System.Activator.CreateInstance (System.Type type) [0x00000] in <filename unknown>:0 
  at System.Collections.Generic.EqualityComparer`1[Newtonsoft.Json.Serialization.DefaultSerializationBinder+TypeNameKey]..cctor () [0x00000] in <filename unknown>:0 
Rethrow as TypeInitializationException: An exception was thrown by the type initializer for System.Collections.Generic.EqualityComparer`1
  at System.Collections.Generic.Dictionary`2[Newtonsoft.Json.Serialization.DefaultSerializationBinder+TypeNameKey,System.Type].Init (Int32 capacity, IEqualityComparer`1 hcp) [0x00000] in <filename unknown>:0 
  at System.Collections.Generic.Dictionary`2[Newtonsoft.Json.Serialization.DefaultSerializationBinder+TypeNameKey,System.Type]..ctor () [0x00000] in <filename unknown>:0 
  at Newtonsoft.Json.Utilities.ThreadSafeStore`2[Newtonsoft.Json.Serialization.DefaultSerializationBinder+TypeNameKey,System.Type].AddValue (TypeNameKey key) [0x00000] in <filename unknown>:0 
  at Newtonsoft.Json.Utilities.ThreadSafeStore`2[Newtonsoft.Json.Serialization.DefaultSerializationBinder+TypeNameKey,System.Type].Get (TypeNameKey key) [0x00000] in <filename unknown>:0 
  at Newtonsoft.Json.Serialization.DefaultSerializationBinder.BindToType (System.String assemblyName, System.String typeName) [0x00000] in <filename unknown>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.Object existingValue) [0x00000] in <filename unknown>:0 
Rethrow as JsonSerializationException: Error resolving type specified in JSON 'LevelRegular, Assembly-CSharp'.
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.Object existingValue) [0x00000] in <filename unknown>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.Object existingValue) [0x00000] in <filename unknown>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueNonProperty (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract) [0x00000] in <filename unknown>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateDictionary (IWrappedDictionary dictionary, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonDictionaryContract contract, System.String id) [0x00000] in <filename unknown>:0 
 
(Filename:  Line: -1)

Any ideas?

Hmm… appears to be an issue with TypeNameHandling. Do you have Skype? I’d like to work with you to get it fixed ASAP.

Yep, my skype: dmitry.minsky

This has been addressed and fixed. Version 1.0.1 has been submitted to the Asset Store and is awaiting approval. IOS 5 seemed to have an issue with structs that implement IEquatable which was being used within Json .Net.

Dustin, thanks for taking the time to create this port of JSON.NET. It’s been much needed. Our company was considering our own port when yours showed up. I have been integrating it into our game but our team is hitting lots of AOT errors when attempting to deserialize data on a device.

More specifically, the library seems to be unable to resolve type names for reasons we can’t guess and it seems to crash deserializing properties that are of type List<> or Dictionary<,> where the generic arguments are not mscorlib types but happen to work fine if they are fields. It also happens if the generic types are abstract. I get the same exceptions that DMinsky is getting.

Secondly, our company uses a set of contracts that are in a shared DLL between our client and server and for various reasons need to use the WCF data contract attributes which the official JSON.NET library interoperates with. I’ve went through the code and saw you ripped out support for it. The marketing material didn’t call out what functionality was ripped out or what version of the JSON.NET library this was even based on. Can you add this back in ASAP? This was an important part of why we paid money for it vs rolling our own library.

tzrafi -

Send me a private message with your Skype and I’ll send you the update to fix the AOT errors with with type resolution and the IEquatable stuff. As for the DataContract support, I can take a look but I’d need to customize it for you. This is something I can probably do. I’ll likely need to reimplement part of .NET (which I had to do for some other features) because there are some things that aren’t available in Unity’s mono implementation.

Specifically, the version of System.Runtime.Serialization that’s included doesn’t have the DataContractAttribute. This was likely stripped because System.Data is also not available.

Just a heads up. We’ve discovered an issue with generic collections not serializing properly in specific (but common) situations when used as properties. When used as Fields instead of Properties they work properly. I am working on a fix and will publish it as soon as it is complete and tested.

I’ve submitted an update to the Asset Store to correct some bugs folks were seeing. I also implemented WCF data attribute support. The update is pending review and will be available as soon as Unity approves it. To those who have purchased, if you send me your Invoice number I can go ahead and get you the updated version right away as it has some important fixes.

Notable Updates:

Version 1.1.0

Corrected bugs with incorrect platform symbols
Improved Android support
Added WCF Data support via:

  • DataContractAttribute
  • DataMemberAttribute
  • EnumMemberAttribute

Created new test cases to cover previous bugs.

How well does this actually work? I must admit I am totally cheezed off with every free JSON parser with Unity that I’ve tried.

Specifically when I tried anything more than was utterly trivial they failed.

What testing have you done on this project with real world JSON?