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,568
    @TopDevilZ - It does compile, it just uses compiler directives that differ based on platform so it is provided as source and compiled by the unity editor.

    As for the code you showed, it looks pretty standard. I need to double check on the null value handling, but everything else looks perfectly normal.
     
  2. RogueCode

    RogueCode

    Joined:
    Apr 3, 2013
    Posts:
    230
  3. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    It is fixed locally, just hasn't made it up to the asset store yet. You can replace the existing vector3 converter with Simons and it should work, if not I can relink the fixed one, ill just have to go back through the threads and find it.
     
    RogueCode likes this.
  4. eezSZI

    eezSZI

    Joined:
    Nov 16, 2012
    Posts:
    121
    I'm running 4.6.4p1, with 4.6.3p4 everything was running smoothly and I was able to Strip ByteCode. Now, unless I have stripping disabled (Android), I get some exceptions:

    04-06 08:47:10.280: I/Unity(6750): NullReferenceException: Object reference not set to an instance of an object
    04-06 08:47:10.280: I/Unity(6750): at System.Reflection.MonoProperty.CreateGetterDelegate (System.Reflection.MethodInfo method) [0x00000] in <filename unknown>:0
    04-06 08:47:10.280: I/Unity(6750): at System.Reflection.MonoProperty.GetValue (System.Object obj, System.Object[] index) [0x00000] in <filename unknown>:0
    04-06 08:47:10.280: I/Unity(6750): at Newtonsoft.Json.Utilities.ReflectionUtils.GetMemberValue (System.Reflection.MemberInfo member, System.Object target) [0x00000] in <filename unknown>:0
    04-06 08:47:10.280: I/Unity(6750): at Newtonsoft.Json.Serialization.ReflectionValueProvider.GetValue (System.Object target) [0x00000] in <filename unknown>:0
    04-06 08:47:10.280: I/Unity(6750): Rethrow as JsonSerializationException: Error getting value from 'SortProblemObjects' on 'SortingProblem'.
    04-06 08:47:10.280: I/Unity(6750): at Newtonsoft.Json.Serialization.ReflectionValueProvider.GetValue (System.Object target) [0x00000] in <filename unknown>:0
    04-06 08:47:10.280: I/Unity(6750): at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue (Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.JsonReader reader, System.O


    Do I need to include System.Reflection in link.xml perhaps? Have you seen this before?

    The odd thing is that "SortProblemObjects" is a list of custom class "ProblemObjects" and I use ProblemObjects serialization elsewhere with no exceptions - just not in a list. (ProblemObject contains, string, int, enum)
     
  5. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Try including reflection in the link file. If that doesn't work we will have to file a bug with unity. Looks like they probably broke the call to GetGetMethod used by reflection to invoke the getter on properties. Let me know if adding to link.xml works.
     
  6. eezSZI

    eezSZI

    Joined:
    Nov 16, 2012
    Posts:
    121
    Thanks for responding so quickly. It didn't seem to help adding reflection:
    Code (csharp):
    1.  
    2. <type fullname="System.Reflection" preserve="all"/>
    3. <type fullname="System.Reflection.MonoProperty" preserve="all"/>
    4.  
    I guess I will try to recreate in a small repo and to try to submit a bug.
     
  7. eezSZI

    eezSZI

    Joined:
    Nov 16, 2012
    Posts:
    121
    One more caveat, if you set the API Compatibility to "Subset" it works. However, my project requires the full ".NET 2.0"

    I've created a small repo and submitted the bug. Case 687143
     
  8. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Thanks! I was going to ask you to submit a bug. Strange that it works with Subset and not with Full. One thing... I have seen something similar happen once before where the stripper actually stripped a property off the object. I wonder if for some reason it is stripping the Get method off of your property. Here's something to try just as a test:

    1. Right before you deserialize, create an instance of the SortProblem class...
    2. Populate that SortProblemObjects property with a new instance (List<SortProblemObjects> or whatever it's type is).
    3. Say var someObject = yourObject.SortProblemObjects.

    so it would looks something like this:

    Code (csharp):
    1.  
    2. var testProblem = new SortProblem();
    3. testProblem.SortProblemObjects = new List<SortProblemObjects>();
    4. var testObjects = testProblem.SortProblemObjects;
    5.  
    6. var deserialized = JsonConvert.DeserializeObject<SortProblem>(yourJson);
    7.  
    If that works that tells me that your Getter is probably getting stripped for some reason...

    Edit: Replace List<SortProblemObjects> with whatever the type is for that property.
     
  9. eezSZI

    eezSZI

    Joined:
    Nov 16, 2012
    Posts:
    121
    Unfortunately that did not work. I even went as far as using all of the constructors and assigning/allocating every member of those classes.
     
  10. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Ok, it looks like Unity must have stripped something from Reflection itself. :/ I'll do some testing and keep an eye on that bug report.
     
  11. zee_ola05

    zee_ola05

    Joined:
    Feb 2, 2014
    Posts:
    166
    Has anyone tried this on XBOX One and PS4 yet?
     
  12. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yes, at least on Xbox one. I would have to give you a special build, but I plan to have the Xbox one directives included in the next update along with webgl.
     
  13. jsil

    jsil

    Joined:
    Jan 15, 2015
    Posts:
    3
    We're having some troubles with some deserialization when doing an iOS il2cppp build.

    We ask it to deserialize a FooBar[] and it gives us back a "FooBar[]" which is actually full of Newtonsoft.Json.Linq.JObjects instead of FooBars.

    What's interesting is that accessing the (nonexistent) properties on the JObjects return null, so it looks like it's returning empty objects.

    I've tracked it down to DefaultContractResolver returning a contract for the System.Object type instead of the FooBar type, but probably need to get a test case put together...
     
  14. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Could you show me the code you're using to deserialize and what your JSON looks like? Also, what version of Unity and does it work properly in the editor? There has been an IL2CPP bug that prevents arrays from deserializing properly and I know there are multiple bug reports into Unity and they may have fixed it in the last patch release for 4.6.x but not 5.0 yet that I know of. If that is what is causing the problem, for now you could use List<FooBar> as a workaround but I'd like to validate the Json first.
     
  15. jsil

    jsil

    Joined:
    Jan 15, 2015
    Posts:
    3
    The following code reproduces the issue.

    On OSX Unity 5.0.1f1 building for iOS 64-bit (il2cpp): Neither a FileInfo[] nor List<FileInfo> work successfully (as described in the the two variants of GetStuff).

    On Windows 8.1 Unity 5.0.1f1 building for HTML5/WebGL: Both variants die with:
    That said, I noticed that the latest version of your library is from November and the one we are using is from July, so I'll try the newer version too, and see what happens.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Linq;
    4. using System.Collections.Generic;
    5. using Newtonsoft.Json;
    6.  
    7.  
    8. public class FileInfo
    9. {
    10.     public string Name;
    11.     public string Md5;
    12.     public short[] SomeNumbers;
    13. }
    14.  
    15.  
    16. static class FileInfoHandler
    17. {
    18.     public const string JSONData = @"
    19. [
    20.    {""name"": ""Red"", ""md5"": ""aa597ae72df137da8e938099f91eb83d"", ""someNumbers"": []},
    21.    {""name"": ""Blue"", ""md5"": ""345635e72df137da8e938099f9145535"", ""someNumbers"": [2, 4, 6, 8]},
    22.    {""name"": ""Green"", ""md5"": ""765173212df137da8e938099f9167677"", ""someNumbers"": [5, 4, 3]},
    23. ]
    24. ";
    25.  
    26.     /** This runs, but the FileInfo[] is filled with JObjects */
    27.     public static FileInfo[] GetStuff() { return JsonConvert.DeserializeObject<FileInfo[]>(JSONData); }
    28.  
    29.     /*
    30.      * This crashes as it runs, throwing an
    31.      * "InvalidCastException: Cannot cast from source type to destination type.
    32.      * at System.Type.GetTypeFromHandle (RuntimeTypeHandle handle) [0x00000] in <filename unknown>:0
    33.      * at System.Array.Copy (System.Array sourceArray, Int32 sourceIndex, System.Array destinationArray, Int32 destinationIndex, Int32 length) [0x00000] in <filename unknown>:0"
    34.      */
    35.     //public static List<FileInfo> GetStuff() { return JsonConvert.DeserializeObject<List<FileInfo>>(JSONData); }
    36.  
    37. }
    38.  
    39.  
    40. public class ArrayOfItems : MonoBehaviour {
    41.     void Start()
    42.     {
    43.         DoThatThing(FileInfoHandler.GetStuff());
    44.     }
    45.  
    46.     public void DoThatThing(IEnumerable<FileInfo> infos)
    47.     {
    48.         foreach (var info in infos)
    49.         {
    50.             if (info.GetType() == typeof (FileInfo))
    51.             {
    52.                 Debug.Log("This guy is okay. " + info.Name + ", " + info.Md5 + ", " + info.SomeNumbers);
    53.                 GetComponent<MeshRenderer>().material.color = Color.green;
    54.             }
    55.             else
    56.             {
    57.                 Debug.LogError("Ohnoes! We have a " + info.GetType());
    58.                 GetComponent<MeshRenderer>().material.color = Color.red;
    59.             }
    60.         }
    61.     }
    62. }
    63.  
     
  16. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    @jsil -

    WebGL won't work for you unless you have the new WebGL build... email me your invoice number and I'll send it. That being said, yes use the newest release as it has collection updates for iOS. But, you'll still need to probably use List instead of Array. And not just List<FileInfo>. Your someNumbers property will have to be a List<int> unless Unity has fixed the array bug.. Try it with the newest Json.Net release first.
     
  17. jsil

    jsil

    Joined:
    Jan 15, 2015
    Posts:
    3
    I updated my version to the one you gave me, changed all the arrays to List<>s and that fixed it for iOS 64 and WebGL, thanks!
     
    Dustin-Horne likes this.
  18. Shorodei

    Shorodei

    Joined:
    Dec 7, 2013
    Posts:
    8
    I'm having issues when deserializing in a web player:

    MethodAccessException: Attempt to access a private/protected method failed.
    at (wrapper managed-to-native) System.Reflection.MonoCMethod:InternalInvoke (object,object[],System.Exception&)

    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

    I saw some discussion of similar issue on the first page of this thread, but I couldn't really find a solution to this.

    Here's my serializing/deserializing code for referece:


    public static string SerializeToBSON(Payload p) {
    byte[] serializedData = new byte[] { };
    using (var stream = new MemoryStream()) {
    using (BsonWriter writer = new BsonWriter(stream)) {
    JsonSerializer serializer = new JsonSerializer();
    serializer.Serialize(writer, p);
    }
    serializedData = stream.ToArray();
    return Convert.ToBase64String(serializedData);
    }
    }

    public static Payload DeserializeFromBSON(string data) {
    byte[] serializedData = Convert.FromBase64String(data);
    using (var stream = new MemoryStream(serializedData)) {
    using (BsonReader reader = new BsonReader(stream)) {
    JsonSerializer serializer = new JsonSerializer();
    return serializer.Deserialize<Payload>(reader);
    }
    }
    }

    Payload object has a bunch of dictionaries.
     
  19. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    I have to go back and check the documentation... BSON serialization of Dictionaries takes some special work I think to make it work but I can't recall off the top of my head.
     
  20. mog-mog-mog

    mog-mog-mog

    Joined:
    Feb 12, 2014
    Posts:
    266
    I have recently purchased the plugin and serializations works fine on Android. But on Ios ILLCP, I am seeing
    Newtonsoft.Json.Schema.JsonSchemaException:get_LinePosition
    Does it support ios 64-bit?
     
  21. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Do you happen to have a full stack trace? Also, could you provide me with a simple repro? It should support IL2CPP just fine (except for an IL2CPP bug that affects arrays). Is this happening during serialization or deserialization? What does the class look like that you're using? And what does the JSON look like and the code that you're using to serialize / deserialize?
     
  22. zee_ola05

    zee_ola05

    Joined:
    Feb 2, 2014
    Posts:
    166
    Hi! I want to NOT serialize some of my fields and properties in my class. I read about [JsonIgnore] but I can't find it in the plugin. What am I missing?
     
  23. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Make sure you add:
    Code (csharp):
    1.  
    2. using Newtonsoft.Json;
    3.  
    At the top of your code. The JsonIgnore attribute is in the Newtonsoft.Json namespace.
     
  24. zee_ola05

    zee_ola05

    Joined:
    Feb 2, 2014
    Posts:
    166
    Awesome, thanks!
     
  25. kreso

    kreso

    Joined:
    Sep 7, 2013
    Posts:
    147
    Hello Dustin,

    Great plugin, I have been using it for a while. Thank you :)

    I happen to run into a problem, and I think it might be connected to the serializer.
    I am serializing some DateTime, and working on calculation (subtracting another DateTime) after deserializing it. However if I run on iOS, game crashes. If I run it on Android it works. Any clues you might have?
    I looked at the serialized data and it looks good (valid numbers).

    ArgumentOutOfRangeException: Argument is out of range.
    at Mono.Globalization.Unicode.SimpleCollator.FilterOptions (Int32 i, CompareOptions opt) [0x00000] in <filename unknown>:0
    at System.DateTime..ctor (Boolean check, TimeSpan value) [0x00000] in <filename unknown>:0
    at System.DateTime.Subtract (TimeSpan value) [0x00000] in <filename unknown>:0
    at System.TimeZone.ToLocalTime (DateTime time) [0x00000] in <filename unknown>:0
    at System.Security.Cryptography.X509Certificates.X509ChainPolicy.Reset () [0x00000] in <filename unknown>:0
    at System.DateTime.ToLocalTime () [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.JsonTextReader.ParseDate (System.String text) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.JsonTextReader.ParseString (Char quote) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.JsonTextReader.ParseValue (Char currentChar) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.JsonTextReader.ReadInternal () [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.JsonTextReader.Read () [0x00000] in <filename unknown>:0
    at UnityEngine.Advertisements.ShowOptions.set_resultCallback (System.Action`1 value) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType (Newtonsoft.Json.JsonReader reader, System.Type t, Newtonsoft.Json.JsonConverter propertyConverter) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject (System.Object newObject, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, System.String id) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateObject (Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, System.String id) [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
    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.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.Serialization.JsonObjectContract.get_ParametrizedConstructor () [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.JsonConvert.DeserializeObject[SampleExternalClass] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.JsonConvert.DeserializeObject[SampleExternalClass] (System.String value) [0x00000] in <filename unknown>:0
    at GameDataSaveLoad.Initialize () [0x00000] in <filename unknown>:0
    at GameDataSaveLoad.get_gameData () [0x00000] in <filename unknown>:0
    at MyLives.RefreshLivesText () [0x00000] in <filename unknown>:0
    at MyLives.Start () [0x00000] in <filename unknown>:0
    at unibill.Dummy.Factory..ctor () [0x00000] in <filename unknown>:0
    unibill.Dummy.Factory:.ctor()
     
  26. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    @kreso - What version of Unity are you using? That was a known IL2CPP bug but I believe it was fixed in:
    5.0.1p1 and 4.6.4p3
     
  27. kreso

    kreso

    Joined:
    Sep 7, 2013
    Posts:
    147
    You were right Dustin! I downloaded latest patch release and it works. Oh boy! And I was in the middle of writing my own wrapper and getting things a lot more complicated :)

    Thanks
     
    Dustin-Horne likes this.
  28. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    You're very welcome.
     
  29. backwheelbates

    backwheelbates

    Joined:
    Jan 14, 2014
    Posts:
    232
    Hi,

    I was about to purchase this for use with Unity 5, although I got a warning from the asset store that this might not be up to date. Just wanted to confirm if this is indeed compatible with the latest Unity5.

    Thanks!

    Eric
     
  30. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yes it is unity 5 compatible. Not sure what the warning is about. Maybe because I publish the package with unity 3.5 since I support all the way back to it.
     
  31. Kronnect

    Kronnect

    Joined:
    Nov 16, 2014
    Posts:
    2,906
    Hi Dustin,

    When I try to deserialize an object that has a byte[] field (using BSON) I got this exception:

    "Error reading bytes. Expected bytes but got StartObject."

    For instance, the following code fails:

    Code (CSharp):
    1.    
    2. public class bsonTest {
    3. public byte[] buffer;
    4. }
    5. ...
    6. bsonTest bt = new bsonTest();
    7.         bt.buffer = new byte[1000];
    8.         for (int k=0;k<1000;k++) bt.buffer[k] = 100;
    9.         byte[] packed = JSONUtil.GetBSON(bt);
    10.         bsonTest bt2 = JSONUtil.Deserialize<bsonTest>(packed);
    11.         for (int k=0;k<1000;k++) {
    12.             if (bt2.buffer[k]!=100) {
    13.                 Debug.Log ("error");
    14.             }
    15.         }
    Auxiliary functions:

    Code (CSharp):
    1. public static byte[] GetBSON (objectobj) {
    2. byte[] serializedData = newbyte[]{};
    3.  
    4. using (varstream = newMemoryStream()) {
    5. using (BsonWriterwriter = newBsonWriter(stream)) {
    6. JsonSerializerserializer = newJsonSerializer ();
    7. serializer.ContractResolver = newWritablePropertiesOnlyResolver ();
    8. serializer.TypeNameHandling = TypeNameHandling.All;
    9. serializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
    10. serializer.NullValueHandling = NullValueHandling.Ignore;
    11. serializer.Serialize (writer, obj);
    12. }
    13.  
    14. serializedData = stream.ToArray ();
    15. }
    16. return serializedData;
    17. }
    18.  
    19.    public static T Deserialize<T> (byte[] serializedData) {
    20.  
    21. T newObject;
    22.  
    23. using (varstream = newMemoryStream(serializedData)) {
    24. using (BsonReaderreader = newBsonReader(stream)) {
    25.  
    26. JsonSerializerserializer = newJsonSerializer ();
    27. serializer.ContractResolver = newWritablePropertiesOnlyResolver ();
    28. serializer.TypeNameHandling = TypeNameHandling.All;
    29. serializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
    30. serializer.NullValueHandling = NullValueHandling.Ignore;
    31. newObject = serializer.Deserialize<T> (reader);
    32. }
    33. }
    34.  
    35. return new Object;
    36. }
    Is there a fix for this?

    Thanks.
     
    Last edited: May 11, 2015
  32. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Hmm I'll take a look and I got your email as well, I'll reply there.
     
  33. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Ok I think I have this fixed, emailed the fix. The update is going tonight with WebGL, Xbox One and PS4 support and will include this patch as well.
     
  34. Kronnect

    Kronnect

    Joined:
    Nov 16, 2014
    Posts:
    2,906
    Thank you. Fixed! This component works magically!
     
    Dustin-Horne likes this.
  35. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    You're very welcome
     
  36. klund

    klund

    Joined:
    Mar 21, 2011
    Posts:
    33
    Thanks for a great product .

    Concerning the new version. Does this mean that unity fixed the bug that required us to replace arrays with lists or have you found a workaround for this webgl problem
     
  37. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    I need to retest that. That was a different issue than what Thrawn had and I'm not sure if they've fixed it yet.

    Edit: I should clarify that Thrawns issue was very specific to having a Byte array as a property of an object and using BSON (not JSON).
     
  38. z000z

    z000z

    Joined:
    Dec 31, 2014
    Posts:
    96
    I ran into a problem where the latest Json.NET serializes DateTimeOffsets in a way that isn't compatible with the Unity version. It looks like the Unity version expects to see a string "/Date("
    " with a value that needs to be converted, but what I actually get from the Json.NET serialization is just the date string. I ended up modifying JsonTextReader.ParseString to see if it fails the check for the "/Date(" string but is supposed to be a ReadType.ReadAsDateTimeOffset to just use the DateTimeOffset.TryParse which works.

    Here's what Json.NET creates:
    \"TimeOffset\": \"2015-05-14T08:33:25.759-06:00\"

    Here's what the Unity version creates:
    \"TimeOffset\":\"\\/Date(1431614005759-0600)\\/\"
     
  39. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Version 1.5.0 has been submitted to the asset store for approval! A little slower than I wanted but I cleaned up a couple of lingering things while I was at it. Current customers can send me their invoice numbers and I can send you the update. Here is the list of updates:

    • WebGL Support - WebGL support is now officially headed to the asset store. It has stabilized enough for me to be comfortable supporting it publicly.
    • Console Defines - I've added support for Xbox One, Xbox 360, PS4 and PS3. I do not have the ability to directly test these platforms but I have worked with customers who are using it on those platforms enough now that I'm comfortable releasing the update. I can still provide support for these platforms, just not directly test.
    • Converter Fixes - The Vector converters were fixed with solutions provided in previous posts so they only serialize the x, y, z and w properties when using the associated converter.
    • Bug Fixes - Fixed a bug that was causing errors deserializing a byte array with BSON serialization. Fixed the previously mentioned JSONNET_XMLDISABLE define to work in the editor.
    • Test / Example Update - Updated the Test Scene so that it now uses the Vector3Converter when running the Vector3 test. This also demonstrates how to use converters for objects you don't control the source for (such as built in Unity objects).
    There are some things I'm working on for the next major update that will come hopefully in the next couple of months. I'm working on the upgrade to a newer release of JSON .NET (going to target v7). I'm also working on putting together some local documentation to ship with the asset rather than relying completely on the online documentation. This will allow me to provide some unity specific examples.

    Lastly, I'm working on adding support for newer unity types that are more difficult to deserialize. With newer releases of JSON .NET supporting CustomCreationConverters this becomes easier to implement without using a hacky solution.
     
    klund likes this.
  40. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yeah the current version doesn't account for a few things and I think treats UTC dates inconsistently (or doesn't apply timezone offsets). That being said, it looks like the format example you gave me takes a type with Ticks and offset. It may require a custom converter to handle or did the change you make fix it?

    Edit: I should also mention that the timezone setting application will be fixed when I get the package updated to a newer release of Json .Net.
     
  41. z000z

    z000z

    Joined:
    Dec 31, 2014
    Posts:
    96
    Yup it looks like it's working now, once you get the package updated I'm guessing the difference will likely fix itself.
     
    Dustin-Horne likes this.
  42. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Version 1.5.0 is now live on the asset store! Converters fixed, Android bug previously mentioned was fixed, Console support added and WebGL support added!

    One note, there appears to be a bug in Unity 5 that only seems to affect consoles, at least Xbox One. I verified this in 5.0.1p4 for Xbox One but it has not been tested yet in 5.0.2 (not sure if Xbox One support is there yet). It appears that in Unity 5, AOT errors are being thrown when accessing properties of built in Unity structs even when using the AOT safe Invoke. This includes for example UnityEngine.Resolution, Vector2, Vector3, Vector4 and Quanternion (and likely Matrix4x4). Creating your own struct to mirror the properties of these objects will work just fine, it's only the built in types that are puking. I have some Converters written that will manually take care of the serialization and deserialization of these types and I'll be attaching them to a future post once they've been thoroughly tested. In the meantime I'll be submitting a bug report to Unity tonight or tomorrow morning when I get back to my development machine.
     
  43. imtrobin

    imtrobin

    Joined:
    Nov 30, 2009
    Posts:
    1,548
    1.5.0 example scene script is missing.
     
  44. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    It's there. It's the texttest script. I just need to build a better test scene. For some reason, when I export to unitypackage or export to the asset store it always breaks the link to that script. I originally thought it was just an ok Unity 3.5 bug but I believe it does it with 5.0 as well.
     
  45. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    @Dustin Horne I'm trying to deserialize an array of a class from a JSON file on a webpage like this:

    Code (csharp):
    1. {"Webvideos":[
    2.     {"video":"LocalizL", "ext":".ogv"},
    3.     {"video":"LocalizR", "ext":".ogv"}
    4. ]}
    Into a Webvideos class that looks like this:
    Code (csharp):
    1. public class Webvideos
    2. {
    3.     public string video = "NoName";
    4.     public string ext = ".ogg";
    5. }
    When I call this code I get a de-serialize error:
    Code (csharp):
    1. var loaded = JsonConvert.DeserializeObject<Webvideos[]>(initFileContents);
    Do you know what might be going wrong?
     
  46. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    @Ben BearFish Yep, you're close. I'll break down the JSON so you understand what you missed:

    Code (csharp):
    1.  
    2. {  //<---  Start object
    3.     "Webvideos": // <-- Object Property named "Webvideos"
    4.     [ // <-- Start Array
    5.         { // <-- Start Object
    6.             "video":"LocalizL",  // <-- "video" property and value
    7.             "ext":".ogv" // <-- "ext" property and value
    8.         } // <-- End Object
    9. ]}
    10.  
    You can match the ends to the starts but basically you have an Object (class) that has a property called Webvideos. That property itself is an array of objects that have "video" and "ext" properties.

    So you'd need something more like this:

    Code (csharp):
    1.  
    2. public class Webvideo
    3. {
    4.     public string video { get; set; }
    5.     public string ext { get; set; }
    6. }
    7.  
    8. public class WebvideoResult
    9. {
    10.     public Webvideo[] Webvideos { get; set;}
    11. }
    12.  
    Now, you would do:

    Code (csharp):
    1.  
    2. var loaded = JsonConvert.DeserializeObject<WebvideoResult>(initFileContents);
    3.  
    As an aside, that array could also be a List<T>, either are appropriate, so your WebvideoResult class could look like:

    Code (csharp):
    1.  
    2. public class WebvideoResult
    3. {
    4.     public List<Webvideo> Webvideos { get; set; }
    5. }
    6.  
     
    Ben-BearFish likes this.
  47. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    Gotcha, thanks so much for the explanation and breakdown.
     
  48. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    You're very welcome :)
     
  49. Lex_Dudya

    Lex_Dudya

    Joined:
    Feb 28, 2013
    Posts:
    29
    Hello, I got an error with iOS IL2CPP build, could you help me?
    The error and some sources below:


    Code (CSharp):
    1.  
    2. void Start ()
    3. {
    4.   serializer = new JsonStringSerializer ();
    5.   var product1 = new Product ();
    6.   var product2 = new Product ();
    7.   var product3 = new Product ();
    8.   var product4 = new Product ();
    9.   var product5 = new Product ();
    10.  
    11.   var productsList = new ProductsData ();
    12.   productsList.Products.Add (product1);
    13.   productsList.Products.Add (product2);
    14.   productsList.Products.Add (product3);
    15.   productsList.Products.Add (product4);
    16.   productsList.Products.Add (product5);
    17.  
    18.   string txt = serializer.Serialize (productsList);
    19.   Debug.Log (txt);
    20.   var deserializedObj = serializer.Deserialize (txt, typeof(ProductsData)) as ProductsData;
    21. }
    22.  
    Code (CSharp):
    1.  
    2. public class ProductsData :  IProductsData
    3.     {
    4.         /// <summary>
    5.         /// List of available products
    6.         /// </summary>
    7.         [JsonProperty("products")]
    8.         public List<IProduct> Products { get; set; }
    9.  
    10.         public ProductsData()
    11.         {
    12.             Products = new List<IProduct>();    
    13.         }
    14. }
    15.  
    16. public class Product :  IProduct
    17.   {
    18.  
    19.         [JsonProperty("id")]
    20.         public Id<IProduct> ProductTypeID { get; set; }
    21.  
    22.  
    23.         [JsonProperty("name")]  
    24.         public string ProductName { get; set; }
    25.  
    26.  
    27.         [JsonProperty("section_id")]
    28.         public Id<IBusinessSector> SectorID { get; set; }
    29.  
    30. #if UNITY_ANDROID || UNITY_EDITOR
    31.         [JsonProperty("version_asset_android")]
    32. #elif UNITY_IOS
    33.         [JsonProperty("version_asset_ios")]
    34. #endif
    35.         public int AssetBundleVersion { get; set; }
    36.  
    37. #if UNITY_ANDROID || UNITY_EDITOR
    38.         [JsonProperty("asset_android")]
    39. #elif UNITY_IOS
    40.         [JsonProperty("asset_ios")]
    41. #endif
    42.         public string AssetBundleURL { get; set; }
    43.   }
    44.  
    P.S. All works fine on PC, Android and iOS Mono2x backend.
     
  50. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    What is JsonStringSerializer? I don't believe that's part of my asset... but it is using it somehow. I'm not sure if I have quite enough information here, but I might know the problem. I have seen IL2CPP for some reason having some trouble with Interfaces when deserializing but generally it's generics that are the issue. Can you try this and see if it fixes the problem? Instead of Products = new List<IProduct> try just new List<Product>.

    Also, you're going to need to use an instance of JsonSerializerSettings with TypeNameHandling set to TypeNameHandling.All so it knows what kind of concrete class to construct in order to populate that list. You'll have to use that both when you serialize and deserialize if you want to use an interface like List<IProduct>. This will add an extra $type parameter to your JSON which tells the serializer what type it is and when you deserialize it will construct that actual type.