Search Unity

JSON .NET for Unity

Discussion in 'Assets and Asset Store' started by Dustin-Horne, Sep 13, 2013.

  1. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    If you reference the DLLs from the asset store package and rebuild your third party package then it shouldn't be an issue as they'll be targeting the correct version. You won't have to use the source or nuget.
     
  2. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Take a look at this article:
    https://www.newtonsoft.com/json/help/html/DeserializeFromBsonCollection.htm

    BSON is a bit different. You'll need to set the following property if your root is a collection (even if it's a list):
    reader.ReadRootValueAsArray = true;
     
    TooManySugar likes this.
  3. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    It's not yet undergone a lot of testing in 2018.1. I'm working on (sorry it's take a while) an update for Netstandard 2.0 support which should increase / fix compatibility issues that some users are seeing.
     
  4. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    This looks like it's failing when trying to create a construtor. This almost always points to a stripping issue. Do you know what object it's failing to deserialize?

    Edit: Saw your update. This is a tough one because the JSON is read with a forward only stream so it doesn't know the size of the data before deserializing. Since it can't initialize an array without knowing the size, it has to create a List<EnumType>() internally, populate it and return as an array. If somewhere in your code you have new List<EnumType>(); then it'll prevent the stripping engine from stripping it and your EnumType[] property should then still work just fine.
     
    TriNityGER likes this.
  5. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Access how? From a JObject? Deserialize?
     
  6. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Interesting, I'll take a look at this. This is a built in converter so I'll check to see if this was intended or if there was a bug fix in the official branch for it.
     
    TriNityGER likes this.
  7. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    What error are you getting when it tries to resolve the type using your custom serialization binder?
     
  8. TriNityGER

    TriNityGER

    Joined:
    Sep 1, 2017
    Posts:
    29
    Thank you very much for your replies :) I had quite some trouble with the 4.x version but after hours of debugging I got everything to work properly and boy it does feel good!
    We're using JSON for all our server-client communication and have quite a lot of stuff to transfer. I was super worried that it might break everything especially when hundreds of thousands of concurrent users exchange JSON data.

    I hate to ask but is there any ETA for a full .Net 4.x release?
     
  9. Link0n3

    Link0n3

    Joined:
    Jun 11, 2015
    Posts:
    4
    Hi Dustin,

    Is there any particular guide for making this work in Android? I am using Unity 5.3.3f1 and would like to switch from XML to Json using this library,targeting from KitKat.
     
  10. royvaneijndhoven

    royvaneijndhoven

    Joined:
    Jun 1, 2017
    Posts:
    66
    Serializing a class/object to JSON that has a Vector2 variable results in two values X and Y. That's perfect but serializing the same class/object that has a Vector2? variable, aka nullable, results in a whole lot more values. Why? We only want the X and Y values.

    To work around this we replaced the Vector2 variable with a struct called Point with two float values X and Y, the Point variable is made nullable. Sadly this causes even more issues in combination with TypeNameHandling.Auto, necessary for our inheritance, on deserialization it'll throw the following exception.

    JsonSerializationException: Could not find type 'System.Nullable`1[[com.company.product.core.savestate.Point, Assembly-CSharp]]' in assembly

    Any ideas?
     
  11. tosiabunio

    tosiabunio

    Joined:
    Jun 29, 2010
    Posts:
    110
    The standalone build can't deserialize my game settings but the game in the editor works just fine. I get the following error message:

    PlatformNotSupportedException: Operation is not supported on this platform.
    at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateDynamicMethod (System.String name, System.Type returnType, System.Type[] parameterTypes, System.Type owner) [0x00018] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateDefaultConstructor[T] (System.Type type) [0x00010] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.Serialization.DefaultContractResolver.GetDefaultCreator (System.Type createdType) [0x00005] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.Serialization.DefaultContractResolver.InitializeContract (Newtonsoft.Json.Serialization.JsonContract contract) [0x00093] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateDictionaryContract (System.Type objectType) [0x00007] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract (System.Type objectType) [0x0007d] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract (System.Type type) [0x00038] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.GetContractSafe (System.Type type) [0x00005] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) [0x0000e] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00053] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x0002d] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value) [0x00000] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at GameSettings.Awake () [0x00052] in <494d13df7cca4988be1873e6288e1024>:0

    What may be the reason for this? I'm using Unity 2018.3.0.
     
    Menion-Leah likes this.
  12. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    664
    @Dustin-Horne I am getting the same `PlatformNotSupportedException: Operation is not supported on this platform` error as mentioned above in build but not in the editor
     
  13. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    664
    @Dustin-Horne | @tosiabunio After looking more closely at my settings, I noticed that while my Scripting Runtime Version was set to the 4.x version, my Api Compatibility Level was still set at 2.0 for some reason, after switching that, the library works fine with an actual build.
     
    gproulx, congressman, Vic070 and 6 others like this.
  14. bradbecker

    bradbecker

    Joined:
    Dec 26, 2014
    Posts:
    97
    Thanks, ryanzec. Was having the same problem.
     
    congressman and vladibo like this.
  15. XaeroDegreaz

    XaeroDegreaz

    Joined:
    Feb 6, 2010
    Posts:
    15
    Standalone IL2CPP builds for Unity 2018.2 seem to be failing during deserialization with this error:

    Code (CSharp):
    1. NotSupportedException: C:\Program Files\Unity\Hub\Editor\2018.2.13f1\Editor\Data\il2cpp\libil2cpp\icalls\mscorlib\System.Reflection.Emit\DynamicMethod.cpp(19) : Unsupported internal call for IL2CPP:DynamicMethod::create_dynamic_method - System.Reflection.Emit is not supported.
    2.   at System.Reflection.Emit.DynamicMethod.CreateDynMethod () [0x00000] in <00000000000000000000000000000000>:0
    3.   at System.Reflection.Emit.DynamicMethod.CreateDelegate (System.Type delegateType) [0x00000] in <00000000000000000000000000000000>:0
    4.   at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateDefaultConstructor[T] (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
    5.   at Newtonsoft.Json.Serialization.JsonArrayContract.CreateTemporaryCollection () [0x00000] in <00000000000000000000000000000000>:0
    6.   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewList (Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonArrayContract contract, System.Boolean& createdFromNonDefaultCreator) [0x00000] in <00000000000000000000000000000000>:0
    7.   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.Object existingValue, System.String id) [0x00000] in <00000000000000000000000000000000>:0
    8.   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x00000] in <00000000000000000000000000000000>:0
    9.   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) [0x00000] in <00000000000000000000000000000000>:0
    10.   at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <00000000000000000000000000000000>:0
    11.   at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <00000000000000000000000000000000>:0
    12.   at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <00000000000000000000000000000000>:0
    13.   at KazBall.KazBallApiClient+<getStatistics>c__Iterator6.MoveNext () [0x00000] in <00000000000000000000000000000000>:0
    14.   at UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) [0x00000] in <00000000000000000000000000000000>:0
    15. (Filename: currently not available on il2cpp Line: -1)
     
    Zankomag likes this.
  16. Grumpy-Dot

    Grumpy-Dot

    Joined:
    Feb 29, 2016
    Posts:
    52
    Hello @Dustin-Horne many thanks for this plugin and the work you have done.
    I am wondering if there are any plans to upgrade this to use Json.Net v12. I am aware that this is now free, and you have little incentive to maintain it, and probably are too busy, but I am just curious if you have planned to upgrade it, and also if you plan to take advantage of the new .Net 4.x Unity version.

    If not, I would appreciate to give us a guide to directly use or adapt the nuget version ourselves. For me personally I am only interested for Win standalone only, but I imagine a lot of people would like it to be cross-platform.

    Many thanks and a happy new year!
     
    jvalenciag and tosiabunio like this.
  17. chanon81

    chanon81

    Joined:
    Oct 6, 2015
    Posts:
    122
    In Windows IL2CPP standalone build using Unity 2018.3.1f1 I am getting this exception:

    Code (CSharp):
    1. NotSupportedException: System.Reflection.Emit.DynamicMethod::.ctor
    2.   at System.Reflection.Emit.DynamicMethod..ctor (System.String name, System.Type returnType, System.Type[] parameterTypes, System.Type owner, System.Boolean skipVisibility) [0x00000] in <00000000000000000000000000000000>:0
    3.   at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateDynamicMethod (System.String name, System.Type returnType, System.Type[] parameterTypes, System.Type owner) [0x00000] in <00000000000000000000000000000000>:0
    4.   at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateDefaultConstructor[T] (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
    5.   at Newtonsoft.Json.Serialization.DefaultContractResolver.InitializeContract (Newtonsoft.Json.Serialization.JsonContract contract) [0x00000] in <00000000000000000000000000000000>:0
    6.   at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateObjectContract (System.Type objectType) [0x00000] in <00000000000000000000000000000000>:0
    7.   at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract (System.Type objectType) [0x00000] in <00000000000000000000000000000000>:0
    8.   at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
    9.   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize (Newtonsoft.Json.JsonWriter jsonWriter, System.Object value, System.Type objectType) [0x00000] in <00000000000000000000000000000000>:0
    10.   at Newtonsoft.Json.JsonSerializer.SerializeInternal (Newtonsoft.Json.JsonWriter jsonWriter, System.Object value, System.Type objectType) [0x00000] in <00000000000000000000000000000000>:0
    11.   at Newtonsoft.Json.JsonSerializer.Serialize (Newtonsoft.Json.JsonWriter jsonWriter, System.Object value) [0x00000] in <00000000000000000000000000000000>:0
    12.   at Newtonsoft.Json.Linq.JToken.FromObjectInternal (System.Object o, Newtonsoft.Json.JsonSerializer jsonSerializer) [0x00000] in <00000000000000000000000000000000>:0
    13.   at Newtonsoft.Json.Linq.JObject.FromObject (System.Object o) [0x00000] in <00000000000000000000000000000000>:0
    EDIT: Seems for Windows it is fixed by using Mono Scripting Backend with .NET 4.x Api Compatibility Level (Can't use .NET Standard 2.0)
     
    Last edited: Jan 14, 2019
    Zankomag likes this.
  18. WnMStudio

    WnMStudio

    Joined:
    Apr 1, 2013
    Posts:
    2
    Is BigInteger still unsupported?
     
  19. joelstartech

    joelstartech

    Joined:
    Mar 6, 2019
    Posts:
    31
    If I'm just storing basic JSON objects under 'user' for simple byte/float arrays, and some simple strings and ints etc, would this be an 'overkill' solution?

    I've never deployed a Unity project to multiple mobile platforms using serialization, so I'm not sure if this would automatically fix any platform-specific errors I'd run into by just adding the Serializable attribute to my structs/classes and then just calling it myself.

    Any insight? Thanks again for all your hard work by the way!
     
  20. ryo0ka

    ryo0ka

    Joined:
    Sep 27, 2015
    Posts:
    32
  21. mnievas

    mnievas

    Joined:
    Apr 22, 2015
    Posts:
    4
    On my Case I change API Compatibility Level. from 2 to .Net 4.x
    THAT WORKED PERFECT
     
  22. Zeratul3D

    Zeratul3D

    Joined:
    Nov 11, 2015
    Posts:
    7
    Sorry @Dustin-Horne for adding also my post to the already long list of help requests, but I find very strange that the same code works in IL2CPP for Android and iOS but not for Windows Standalone.
    It seems to me it cannot be such a crippling bug and there must be a reasonable solution/fix for it (but at the same time far beyond for my capabilities).

    You can try this code if you need to replicate the issue:


    Code (CSharp):
    1.  
    2. public class JsonableStuff : MonoBehaviour
    3. {
    4.     // Start is called before the first frame update
    5.     void Start()
    6.     {
    7.             var filepath = @"D:\Test\test.json";
    8.             var text = File.ReadAllText(filepath);
    9.  
    10.             var result = JsonConvert.DeserializeObject<TestSimpleJson>(text);
    11.     }
    12. }
    13.  
    14. [System.Serializable]
    15. public class TestSimpleJson
    16. {
    17.     public string testString { get; set; }
    18.     public int testInt { get; set; }
    19.     public float testFloat { get; set; }
    20.     public bool testBool { get; set; }
    21. }
    22.  

    Here's the example json:


    Code (JavaScript):
    1.  
    2. {
    3.     "testString": "string value",
    4.     "testInt": 1,
    5.     "testFloat": 1.2,
    6.     "testBool": true
    7. }
    8.  

    And the infamous error:

    Code (CSharp):
    1.  
    2. NotSupportedException: System.Reflection.Emit.DynamicMethod::.ctor
    3.   at System.Reflection.Emit.DynamicMethod..ctor (System.String name, System.Type returnType, System.Type[] parameterTypes, System.Type owner, System.Boolean skipVisibility) [0x00000] in <00000000000000000000000000000000>:0
    4.   at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateDynamicMethod (System.String name, System.Type returnType, System.Type[] parameterTypes, System.Type owner) [0x00000] in <00000000000000000000000000000000>:0
    5.   at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateDefaultConstructor[T] (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
    6.   at Newtonsoft.Json.Serialization.DefaultContractResolver.InitializeContract (Newtonsoft.Json.Serialization.JsonContract contract) [0x00000] in <00000000000000000000000000000000>:0
    7.   at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateObjectContract (System.Type objectType) [0x00000] in <00000000000000000000000000000000>:0
    8.   at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract (System.Type objectType) [0x00000] in <00000000000000000000000000000000>:0
    9.   at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
    10.   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) [0x00000] in <00000000000000000000000000000000>:0
    11.   at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <00000000000000000000000000000000>:0
    12.   at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <00000000000000000000000000000000>:0
    13.   at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <00000000000000000000000000000000>:0
    14.  
    It seems to me something related to AOT and not to assembly stripping, but again I can't understand how it's possible that Window's Standalone will cause problems while iOS is not.

    Thanks for your help and for the great tool!

    A
     
    royvaneijndhoven likes this.
  23. Ori_Lazar

    Ori_Lazar

    Joined:
    Nov 8, 2015
    Posts:
    1
    I love you, you saved my day. Good day to you sir!
     
  24. denlee0710

    denlee0710

    Joined:
    Mar 9, 2015
    Posts:
    29
    Does this mean this asset will require .Net 4.x api compatibility level on mobile? I would much prefer targeting .Net 2.0 for build size reasons...
     
  25. FBones

    FBones

    Joined:
    Aug 28, 2016
    Posts:
    66
    @Dustin-Horne , are there plans to update this to a more recent JSON.net version?

    For example, in the unity version the ContainsKey method for JObject is not public. This was fixed in version 11.
     
  26. Phong

    Phong

    Joined:
    Apr 12, 2010
    Posts:
    1,607
    Any word on a compitibility level .Net 2.0 Standard compatible version? We too are getting the error bellow. Our tech lead says we can't use 4.x compatibility because it would bloat the client too much.

    We are getting the errors (on Linux platform):

    PlatformNotSupportedException: Operation is not supported on this platform.
    at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateDynamicMethod (System.String name, System.Type returnType, System.Type[] parameterTypes, System.Type owner) [0x00018] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateDefaultConstructor[T] (System.Type type) [0x00010] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    at Newtonsoft.Json.Serialization.DefaultContractResolver.GetDefaultCreator (System.Type createdType) [0x00005] in <97722d3abc9f4cf69f9e21e6770081b3>:0
    ....
     
  27. Phong

    Phong

    Joined:
    Apr 12, 2010
    Posts:
    1,607
    UPDATE: For anyone wanting to use the .Net 4.x with the API Compatibility 2.0 Standard. Here is a solution.

    The System.Reflection.Emit namespace has been stripped down in the API Compatibility 2.0 Standard. Any code that tries to use anything in the System.Reflection.Emit namespace will fail. There are three versions of the JsonDotNet plugin in the project. Two of these try to use the System.Reflection.Emit namespace. The AOT version does not.

    Solution:

    In the JsonDotNet/Assemblies folder, visit each of the "Newtonsoft.Json" assemblies (there should be three in: AOT, Standalone, Windows). Configure them so that AOT is used for all platforms and Standalone and Windows are not used for any platform.
     
  28. Harriet92

    Harriet92

    Joined:
    Jul 2, 2015
    Posts:
    3
    Hi guys!
    I have this strange issue only on iOS - when I'm trying to serialize an object with an interface array it just stops without throwing any errors - I have debug logs before and after serialization and the first log always appears on console, and the other one only when I do not have the IInterface[] field in the dto object.


    Code (CSharp):
    1. private JsonSerializerSettings allNameHandlingSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All, NullValueHandling = NullValueHandling.Ignore };
    2.  
    3.     public string Serialize<T>(T objectToSerialize)
    4.     {
    5.         Debug.Log("Serializing...");
    6.         var str = JsonConvert.SerializeObject(objectToSerialize, Formatting.Indented, allNameHandlingSettings);
    7.         Debug.Log("Finished serializing");
    8.         return str;
    9.     }
    works for


    Code (CSharp):
    1. [Serializable]
    2.     private class DtoTest
    3.     {
    4.         public string TestString;
    5.     }
    silently fails before writing the second log for:


    Code (CSharp):
    1. [Serializable]
    2.     private class DtoTest
    3.     {
    4.         public string TestString;
    5.         public IComponent[] components;
    6.     }
    Do you have any ideas? Apart from that it works perfectly...
     
    Last edited: May 24, 2019
  29. WheresMommy

    WheresMommy

    Joined:
    Oct 4, 2012
    Posts:
    888
    Please use code tags
     
    Harriet92 likes this.
  30. gm0124816

    gm0124816

    Joined:
    Sep 12, 2017
    Posts:
    4
    Thanks Phong ! Works great for IL2CPP on Windows as well ! No more errors and everything working as supposes so far !

    Will do extended testing next days.
     
  31. chanon81

    chanon81

    Joined:
    Oct 6, 2015
    Posts:
    122
    Anyone know if there is a "DeepEquals" function? A way to compare two JObjects if all there property and inner property values are equal.

    Or would it be more efficient to just use ToString and compare the strings?
     
  32. WheresMommy

    WheresMommy

    Joined:
    Oct 4, 2012
    Posts:
    888
    I am using functions like this below to compare my structure and then to update or delete entries from the class object generated by the stored and the update json coming from an REST API. So what are you exactly trying to do there?

    Code (CSharp):
    1. public void UpdateJsonObjectsByID(GamesData objectToUpdate, GamesData update)
    2.     {
    3.         FieldInfo[] fields = update.GetType().GetFields();
    4.  
    5.         //Iterate through first level arrays like (GameData, AnswerData etc.)
    6.         foreach (FieldInfo field in fields)
    7.         {
    8.             var fieldValue = field.GetValue(update);
    9.  
    10.             if (fieldValue != null)
    11.             {
    12.                 //Get all items inside the first level arrays like id etc. with their specific types
    13.                 foreach (var item in fieldValue as IList)
    14.                 {
    15.                     if (item != null)
    16.                     {
    17.                         try
    18.                         {
    19.                             int itemID = (int)item.GetType().GetField("id").GetValue(item);
    20.                             bool itemActive = (bool)item.GetType().GetField("active").GetValue(item);
    21.  
    22.                             var sourceValues = field.GetValue(objectToUpdate);
    23.                             bool addItem = true;
    24.                             //Iterate through all source values in the list we want to update
    25.                             foreach (var sourceItem in sourceValues as IList)
    26.                             {
    27.                                 //Does any of them have the same id?
    28.                                 if ((int)sourceItem.GetType().GetField("id").GetValue(sourceItem) == itemID)
    29.                                 {
    30.                                     //Check all the fields inside that update datafield, update the source field if it is not null
    31.                                     foreach(FieldInfo itemField in item.GetType().GetFields())
    32.                                     {
    33.                                         bool deleteItem = false;
    34.  
    35.                                         if(itemField != null)
    36.                                         {
    37.                                             addItem = false;
    38.  
    39.                                             //Update each field like id and answer inside the item
    40.                                             foreach(FieldInfo sourceField in sourceItem.GetType().GetFields())
    41.                                             {
    42.                                                 if (sourceField.Name == itemField.Name)
    43.                                                 {
    44.                                                     //AddToDebugLog("Updating " + sourceField.Name + " to " + itemField.GetValue(item));
    45.                                                     sourceField.SetValue(sourceItem, itemField.GetValue(item));
    46.                                                 }
    47.  
    48.                                                 //Check for active state, if false, set remove flag
    49.                                                 if(sourceField.Name == "active")
    50.                                                 {
    51.                                                     if ((bool)sourceField.GetValue(item) == false)
    52.                                                     {
    53.                                                         deleteItem = true;
    54.                                                     }
    55.                                                 }
    56.                                             }
    57.  
    58.                                             //If remove flag, remove it from the local updated gamestate, even if it was published
    59.                                             if (deleteItem)
    60.                                             {
    61.                                                 //AddToDebugLog("Removing " + sourceItem.GetType().GetField("id").GetValue(sourceItem));
    62.                                                 IList sourceValuesList = sourceValues as IList;
    63.                                                 sourceValuesList.Remove(sourceItem);
    64.                                             }
    65.                                         }
    66.                                     }
    67.                                 }
    68.                             }
    69.  
    70.                             //If item is not present so we can add it, check if is active set to true, if not, dont add empty active false values
    71.                             if(addItem && itemActive)
    72.                             {
    73.                                 //AddToDebugLog("Adding " + item.GetType().GetField("id").GetValue(item));
    74.                                 IList sourceValuesList = sourceValues as IList;
    75.                                 sourceValuesList.Add(item);
    76.                             }
    77.                             else
    78.                             {
    79.                                 //AddToDebugLog("Item " + item.GetType().GetField("id").GetValue(item) + " is active: " + itemActive + " or not present!");
    80.                             }
    81.                         }
    82.                         catch
    83.                         {
    84.                             AddToDebugLog("No entry found");
    85.                         }
    86.                     }
    87.                 }
    88.             }
    89.         }
    90.     }
     
    chanon81 likes this.
  33. XaeroDegreaz

    XaeroDegreaz

    Joined:
    Feb 6, 2010
    Posts:
    15
    If you're deserializing JSON into custom objects, you can override the ToString and HashCode of the objects to perform a "deep equals".

    Also, if you're deserializing into a Dictionary object, you can do something like

    Code (CSharp):
    1. dic1.Count == dic2.Count && !dic1.Except(dic2).Any();
     
    Last edited: Jul 3, 2019
    chanon81 likes this.
  34. chanon81

    chanon81

    Joined:
    Oct 6, 2015
    Posts:
    122
  35. HD30

    HD30

    Joined:
    Dec 30, 2015
    Posts:
    7
    Is there any way to get an updated version from JSON 8.0.0? Many code libraries today use 10.0.0 and above. Is there a way to manually update the JSON library?
    Thank you!
     
  36. Trivium_Dev

    Trivium_Dev

    Joined:
    Aug 1, 2017
    Posts:
    65
    Running into an issue trying to serialize a Color. It crashes Unity completely, I don't get an error messages. What's weird is that if all the RGBA values are whole values (0 or 1), it'll work, but if any are decimals (i.e., 0.5f) it doesn't work.

    Here's my code:
    Code (CSharp):
    1. string json = JsonConvert.SerializeObject(new Color(0.5f, 0.5f, 0.5f, 1), new JsonSerializerSettings()
    2.         {
    3.             ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    4.             DateFormatHandling = DateFormatHandling.IsoDateFormat,
    5.             DateTimeZoneHandling = DateTimeZoneHandling.Unspecified
    6. #if UNITY_EDITOR
    7.                     , // while in the editor, format the JSON so that it is easier to read
    8.             Formatting = Formatting.Indented
    9. #endif
    10.         });
    I'm currently using Unity 2018.4.6 and JSON .Net for Unity 2.0.1 (latest version on the store).
     
  37. yaswanth

    yaswanth

    Joined:
    Mar 17, 2014
    Posts:
    1
    Is there a way to serialize list in list.

    For example :
    {
    "nested_list":[
    [1.1,2.2,3.3,4.4],
    [1.1,2.2,3.3,4.4],
    [1.1,2.2,3.3,4.4],
    [1.1,2.2,3.3,4.4]
    ]
    }
     
  38. sbethge

    sbethge

    Joined:
    Mar 20, 2019
    Posts:
    2
    Maybe that has changed but it is open source under the GPL, so no reason to not include it.
     
  39. Rasmusmn

    Rasmusmn

    Joined:
    Nov 20, 2018
    Posts:
    3
    I get this Exception when running my iOS or webGL build with the newest version of JSON .Net for Unity, scripting runtime 3.5 and api compatibility level 2.0:

    Code (CSharp):
    1. ExecutionEngineException: Attempting to call method 'System.Collections.Generic.List`1[[System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]::.cctor' for which no ahead of time (AOT) code was generated.
    2. UnityLoader.js:4   at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters, System.Exception& exc) [0x00000] in <filename unknown>:0
    3. UnityLoader.js:4   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
    4. UnityLoader.js:4   at System.Reflection.MonoCMethod.Invoke (BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
    5. UnityLoader.js:4   at System.Reflection.ConstructorInfo.Invoke (System.Object[] parameters) [0x00000] in <filename unknown>:0
    6. UnityLoader.js:4   at Newtonsoft.Json.Utilities.LateBoundReflectionDelegateFactory+<>c__DisplayClass5_0`1[System.Object].<CreateDefaultConstructor>b__1 () [0x00000] in <filename unknown>:0
    7. UnityLoader.js:4   at System.Func`1[System.Object].Invoke () [0x00000] in <filename unknown>:0
    8. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonArrayContract.CreateTemporaryCollection () [0x00000] in <filename unknown>:0
    9. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewList (Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonArrayContract contract, Boolean& createdFromNonDefaultCreator) [0x00000] in <filename unknown>:0
    10. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.Object existingValue, System.String id) [0x00000] in <filename unknown>:0
    11. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x00000] in <filename unknown>:0
    12. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue (Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.JsonConverter propertyConverter, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, Newtonsoft.Json.JsonReader reader, System.Object target) [0x00000] in <filename unknown>:0
    13. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject (System.Object newObject, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.String id) [0x00000] in <filename unknown>:0
    14. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x00000] in <filename unknown>:0
    15. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x00000] in <filename unknown>:0
    16. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue (Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.JsonConverter propertyConverter, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, Newtonsoft.Json.JsonReader reader, System.Object target) [0x00000] in <filename unknown>:0
    17. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject (System.Object newObject, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.String id) [0x00000] in <filename unknown>:0
    18. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x00000] in <filename unknown>:0
    19. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x00000] in <filename unknown>:0
    20. UnityLoader.js:4   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, Boolean checkAdditionalContent) [0x00000] in <filename unknown>:0
    21. UnityLoader.js:4   at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <filename unknown>:0
    22. UnityLoader.js:4   at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <filename unknown>:0
    23. UnityLoader.js:4   at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <filename unknown>:0
    24. UnityLoader.js:4   at Newtonsoft.Json.JsonConvert.DeserializeObject[Object] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <filename unknown>:0
    25. UnityLoader.js:4   at Newtonsoft.Json.JsonConvert.DeserializeObject[Object] (System.String value) [0x00000] in <filename unknown>:0
    Edit: I tried building with different Unity versions including Unity 2018.3.14f1 and 2018.4.9f1.
    I tried the solution with the link.xml, but that did not solve the issue. (why not!?)

    Solved: I added the (hack) line
    [ICODE]var dontStripMe = new List<System.Boolean>();
    [/ICODE]
    to my script just before calling JsonConvert.DeserializeObject
     
    Last edited: Sep 19, 2019
    glitchers likes this.
  40. rerwandi

    rerwandi

    Joined:
    Dec 8, 2014
    Posts:
    531
    I have the same issues with deserializing to ScriptableObject, any examples how to create this kind of CustomCreationHandler?
     
  41. HakanOzcan

    HakanOzcan

    Joined:
    May 14, 2013
    Posts:
    37
    It is pretty much strange that one of worlds most used JSON library is not compatible with unity(i mean IL2CPP), and one guy(@Dustin-Horne) is trying to do some things to solve such a very popular problem, but neither plugin nor forum thread is updated(Newtonsofts Json.NET current version is 12.0.2), but i dont see any Unity crew here. It is so strange!
     
    tosiabunio likes this.
  42. Trivium_Dev

    Trivium_Dev

    Joined:
    Aug 1, 2017
    Posts:
    65
    I think this is what you are looking for, I haven't tested it extensively but I use a similar pattern for other custom data types that have weird conversions.
    Code (CSharp):
    1. using System;
    2. using Newtonsoft.Json;
    3. using Newtonsoft.Json.Linq;
    4. using UnityEngine;
    5.  
    6. namespace CustomJsonConverters
    7. {
    8.     public class ScriptableObjectConverter<T> : JsonConverter where T : ScriptableObject
    9.     {
    10.         public override bool CanConvert(Type objectType)
    11.         {
    12.             return objectType == typeof(T);
    13.         }
    14.  
    15.         public override bool CanWrite
    16.         {
    17.             get { return false; }
    18.         }
    19.  
    20.         public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    21.         {
    22.             if(reader.TokenType == JsonToken.Null)
    23.             {
    24.                 return null;
    25.             }
    26.             else
    27.             {
    28.                 JObject jObject = JObject.Load(reader);
    29.  
    30.                 // Create target object based on JObject
    31.                 T tmp = ScriptableObject.CreateInstance<T>();
    32.  
    33.                 // Populate the object properties
    34.                 serializer.Populate(jObject.CreateReader(), tmp);
    35.  
    36.                 return tmp;
    37.             }
    38.         }
    39.  
    40.         public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    41.         {
    42.             serializer.Serialize(writer, value); // honestly I don't think this does anything since CanWrite is false
    43.         }
    44.     }
    45. }
    Then you would create your ScriptableObject class like this:
    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Collections.ObjectModel;
    4. using Newtonsoft.Json;
    5. using UnityEngine;
    6. using CustomJsonConverters;
    7.  
    8. namespace CustomScriptableObject
    9. {
    10.     [JsonObject(MemberSerialization.OptIn)] // optional, use if you only want to include certain fields
    11.     [JsonConverter(typeof(ScriptableObjectConverter<MyCustomScriptableObject>))]
    12.     [CreateAssetMenu(menuName = "MyCustomScriptableObject", order = 100)]
    13.     public class MyCustomScriptableObject : ScriptableObject
    14.     {
    15.         [SerializeField]
    16.         [JsonProperty("string_example")]
    17.         private string stringExample = "this is a test string";
    18.         [SerializeField]
    19.         [JsonProperty("int_example")]
    20.         private int intExample = 10;
    21.         [SerializeField]
    22.         [JsonProperty("list_example")]
    23.         private List<string> listExample = new List<string>();
    24.         [SerializeField]
    25.         [JsonProperty("bool_example")]
    26.         private bool boolExample = true;
    27.     }
    28. }
    Then you just serialize/deserialize normally:
    Code (CSharp):
    1. using System;
    2. using Newtonsoft.Json;
    3. using CustomScriptableObject;
    4. using UnityEngine;
    5.  
    6. public class Test : MonoBehaviour
    7. {
    8.     public MyCustomScriptableObject test;
    9.     public ChildClass testWithChild;
    10.  
    11.     // Start is called before the first frame update
    12.     void Start()
    13.     {
    14.         string json = JsonConvert.SerializeObject(test);
    15.         Debug.Log(json);
    16.  
    17.         this.test = JsonConvert.DeserializeObject<MyCustomScriptableObject>(json);
    18.  
    19.         json = JsonConvert.SerializeObject(testWithChild);
    20.         Debug.Log(json);
    21.  
    22.         this.testWithChild = JsonConvert.DeserializeObject<ChildClass>(json);
    23.  
    24.         JsonConvert.PopulateObject(json, testWithChild);
    25.     }
    26.  
    27.     [Serializable]
    28.     public class ChildClass
    29.     {
    30.         public MyCustomScriptableObject test;
    31.     }
    32. }
    Some notes: I'm not taking into account any JSON de/serialization settings, like "DefaultValueHandling", "PreserveReferencesHandling", "ObjectCreationHandling", and "NullValueHandling". So for example if you have "ObjectCreationHandling" set to "Auto", it will still create new instances of your scriptable objects instead of reusing them. But this is at least a start - I generally don't use many of those settings or the way I write the custom JsonConverter is how I expect it to work for that type anyway, regardless of setting, but depending on your needs you might get unexpected results unless you go in and take into account all of those settings.

    One last thing - I don't quite understand the "CanWrite" and the "WriteJson" functions - I get reference loop errors unless "CanWrite" returns false and for the life of me I don't get why. It still writes the class out to JSON correctly though so.... I don't worry about it.
     
    Wajdik likes this.
  43. Player7

    Player7

    Joined:
    Oct 21, 2015
    Posts:
    1,478
    Is this not being updated anymore, just coming back to a project where I used this alot as unity's built in json support is rubbish compared to the features of this... only this hasn't been updated in a while ..is no one maintaining it?

    @Dustin-Horne been gone for a year? :/
     
  44. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    1,198
    I wanted a good json lib for runtime serializing/deserializing but this seems out of date and json.net still not comaptible? Anyone found another good JSON lib they use with Unity?
     
  45. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    48
    I'm using this fork of Newtonsoft.Json
    https://github.com/jilleJr/Newtonsoft.Json-for-Unity
     
    Player7, jGate99 and andyz like this.
  46. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    953
  47. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    48
    You could always make some quick tests with IL2CPP on WebGL. If it runs on WebGL then it would be so on other AOT platforms.
     
    jGate99 likes this.
  48. GreatMightyMoe

    GreatMightyMoe

    Joined:
    Jul 20, 2016
    Posts:
    7
    Hello,

    I have a encountered a problem, where Newtonsoft.Json seems to be lacking a method. I am on Unity 2019.1.3f1 and I am building for HoloLens.

    When I try to deserialize to a specific class, I get the following error:
    Code (CSharp):
    1. ExecutionEngineException: Attempting to call method 'Newtonsoft.Json.Utilities.CollectionWrapper`1[[System.UInt32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]::.ctor' for which no ahead of time (AOT) code was generated.
    I looked up the class CollectionWrapper and the Preserve attribute is set. I don't know what is the problem, maybe the signature is wrong? The error message says something about UInt32, in COllectionWrapper I found only IList int.
    How could I fix this?

    I'll attach the stacktrace, the json I'm deserializing and the class I'm trying to create from the Json. Some help would be greatly appreciated!
     

    Attached Files:

  49. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    48
    This is a typical AOT problem when working with a serializer that depends on reflection. AOT platforms such as iOS, WebGL prohibit you from generating the actual implementation of <T> generics at runtime.

    What is the source of Newtonsoft.Json library that you are using? Have you tried this out https://github.com/jilleJr/Newtonsoft.Json-for-Unity ?
     
  50. GreatMightyMoe

    GreatMightyMoe

    Joined:
    Jul 20, 2016
    Posts:
    7
    I'm using ParentElements Json.net from the unity asset store, so I assume this must be the source:
    https://github.com/ianmacgillivray/...ewtonsoft.Json/Utilities/CollectionWrapper.cs
    I even donloaded the whole project and compiled it with an added constructor that takes an int32 and spammed the preserve attribute everywhere, but no luck! Still the same error message. Did I even understand the error correctly?
    ExecutionEngineException: Attempting to call method 'Newtonsoft.Json.Utilities.CollectionWrapper`1[[System.UInt32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]::.ctor' for which no ahead of time (AOT) code was generated.

    This means that it's calling the CollectionWrapper contrsuctor with an int32 as an parameter, but no constructor with this signature exists, or doesn't it?

    Also thank you for suggesting another json solution for unity. Unfortunately, jilleJrs solustion doesn't work for me. When it tries to deserialize a string into a class, it throws this error:
    FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies.

    Pretty weird, because in the visual studio projec all depoendencies are set to the jillerJr dlls. I also made sure to delete ParentElements json solution from the project before adding the new one.
    I even get this error when I install the package on a completely new empty project.
    And the same happens with SaladLabs json solution...

    I'm at a complete loss here and and I'm really running out of ideas.
     
unityunity