Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

JSON .NET for Unity

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

  1. mwgray

    mwgray

    Joined:
    Feb 18, 2015
    Posts:
    5
    Hi Dustin,

    I'm running into the same issue that @s0lt4r with regard to serializing a Sprite.

    I believe what is happening is the serializer gets to a UnityEngine.Sprite object and tries to dig down into it's properties instead of storing a reference in it's place. Unity's (de)serializer stores a reference to a sprite and converts it before/after the serialization:
    Code (CSharp):
    1. sprite: {fileID: 21300000, guid: 658df5821e9344e4e89e2d3ab86e4e02, type: 3}
    It seems as if a JsonConverter is needed for any library asset references.
     
  2. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yeah I've been looking at this. I think the problem is the Texture property which returns a Texture2D, which also has blackTexture and whiteTexture properties so it might be creating a circular reference. In this case a JsonConverter would be more appropriate anyway because there are several properties you probably don't care about serializing at all, such as the calculated properties (i.e. triangles and vertices).

    I'm also not super familiar with sprites. How are they created? Is it just the Sprite.Create function and no constructor?
     
  3. mwgray

    mwgray

    Joined:
    Feb 18, 2015
    Posts:
    5
    In my case, it's all in the unity editor. I'm importing a png as a sprite and then updating my object's Sprite property with the editor. I tried throwing something together using JsonConverter, but I'm not familiar enough with the systems. My main worry is Unity is doing some behind the scenes magic that isn't exposed publicly and cannot be extended.

    In a similar vein is storing prefab references. It's likely the same issue, because Unity stores references for prefabs as well. Basically any data member that is an asset (and populated via the project window) will have this issue.
     
  4. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    I'm pretty sure that's the case. Type is the object type. "guid" is the object guid, and fileid tells Unity where it has the data serialized.
     
  5. cleromancer

    cleromancer

    Joined:
    Feb 3, 2015
    Posts:
    5
    Hi Dustin, this has been a great asset store purchase, I've been using it for a while now. Are you still planning on publishing an update in the near future to fix Universal Windows 10 builds?

    Thanks!
     
  6. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    yes i am
     
    cleromancer likes this.
  7. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    @Dustin Horne I noticed you have a XML node converter in the source code. Does that mean we can use that to read XML files, or is that for something else?

    And if not, would it be beyond the scope of your plugin to add XML for the plugin as well.
     
  8. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    yes it can read xml and fragments as well, though it's really only useful if you want to use the jobject system to access data. I'm also working on a current bug that is preventing xml conversion from working on webgl and I haven't tracked down the cause yet.

    As far as xml goes, it's not an xml serializer but has the ability to read in xml and convert to json or a jobject which can be further deserialized into an object.
     
  9. Tongie

    Tongie

    Joined:
    Sep 19, 2012
    Posts:
    90
    Hi dustin, may I know the json.net version in this plugin? is it the latest 7.0 or 7.0.1
     
  10. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Right now it depends on the platform. Most platforms are actually still on 4.3 but with some of the later bug fixes retrofitted in. WinRT is on 5.8. And Windows 10 which I'm working up a release for is 7.0. Sometime soon, though I don't yet have an ETA, I'll have all platforms on the 7.x version line and have them unified.
     
  11. yuwen-lian

    yuwen-lian

    Joined:
    Sep 25, 2015
    Posts:
    5
    Hi Dustin,

    When I set the Api Compatibility Level to .NET 2.0, there shows three errors:

    Assets/JsonDotNet/Source/Linq/LinqExtensions.cs(93,53): error CS0121: The call is ambiguous between the following methods or properties: `Newtonsoft.Json.Linq.Extensions.AsJEnumerable<Newtonsoft.Json.Linq.JProperty>(this System.Collections.Generic.IEnumerable<Newtonsoft.Json.Linq.JProperty>)' and `Newtonsoft.Json.Linq.LinqExtensions.AsJEnumerable<Newtonsoft.Json.Linq.JProperty>(this System.Collections.Generic.IEnumerable<Newtonsoft.Json.Linq.JProperty>)'

    Assets/JsonDotNet/Source/Linq/LinqExtensions.cs(148,20): error CS0121: The call is ambiguous between the following methods or properties: `Newtonsoft.Json.Linq.Extensions.Value<Newtonsoft.Json.Linq.JToken,U>(this System.Collections.Generic.IEnumerable<Newtonsoft.Json.Linq.JToken>)' and `Newtonsoft.Json.Linq.LinqExtensions.Value<Newtonsoft.Json.Linq.JToken,U>(this System.Collections.Generic.IEnumerable<Newtonsoft.Json.Linq.JToken>)'

    ssets/JsonDotNet/Source/Linq/LinqExtensions.cs(291,21): error CS0121: The call is ambiguous between the following methods or properties: `Newtonsoft.Json.Linq.Extensions.AsJEnumerable<Newtonsoft.Json.Linq.JToken>(this System.Collections.Generic.IEnumerable<Newtonsoft.Json.Linq.JToken>)' and `Newtonsoft.Json.Linq.LinqExtensions.AsJEnumerable<Newtonsoft.Json.Linq.JToken>(this System.Collections.Generic.IEnumerable<Newtonsoft.Json.Linq.JToken>)'

    Do I have to use .NET 2.0 Subset for this plugin? Or is there a fix for this problem?
    btw, I'm using Unity 5.2.1p2.

    Thanks.
     
  12. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    According to your error, it is conflicting with itself. Not exactly though. I'm betting that one of your other assets has included a Newtonsoft.Json.dll (the official release). Some packages do this as they use it for serialization and deserialization in the editor. Find that DLL and delete it and your other packages will use my asset instead automatically which will make that error go away.
     
  13. Xylph

    Xylph

    Joined:
    Dec 11, 2013
    Posts:
    30
    Hi again. I'm wondering if I'm doing something wrong because I'm getting very weird bugs. 2 different bugs.

    I'll describe my setup first. I wrote an extension for GameObject and MonoBehaviour so that I can serialize/deserialize Unity objects with one line of code. I'm also using the classes in Json.Linq namespace since I want to have full control on what's being serialized. Mind that I'm already using this setup since early last year and it was working perfectly (Unity 4.5 or 4.6).

    Here are the weird bugs:

    #1
    Suddenly, it hangs during deserialization (loading game from save file) on mobile only. For PC and web, it's still working. If I remember it correctly, this started to happen after Unity 5 was released. I can repro this 100%.

    EDIT: It works on WebGL but only on Firefox.

    #2
    I have a JArray serialized containing 70 JObjects. On deserialization, I'm iterating over the JArray using foreach loop (also tried for loop just to be sure). The weird behavior is that the loop only runs once (only the first element) then it skips through all the remaining 69 elements.

    And another weird thing is that this doesn't happen to all cases. To give you a background, I have a character with unique achievements. These achievements are run-time generated and stored in a JArray when serialized for each character. The first character being serialized didn't have the problem but the following characters were only able to load one of the 70-ish achievements.

    Is there a limit or something? That's the only assumption I can draw since I've added tons of data since then.

    I'm also not sure if the 2 bugs I'm encountering are related.
     
    Last edited: Jan 2, 2016
  14. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
    Hello Dustin,

    Do you have an example of how to Serialize and Deserialize a Vector3? I have look all over but I can't seem to find any reference about this.

    This is what I tried:


    Code (CSharp):
    1.  
    2. using Newtonsoft.Json;
    3.  
    4. Vector3 pPosition = thePlayerTransform.position;
    5. string myPlayerSerializedData=JsonConvert.SerializeObject(pPosition);
    6. var myPlayerDeserializedData = JsonConvert.DeserializeObject(myPlayerSerializedData);
    7. Debug.Log(myPlayerDeserializedData);
    8.  
    This is what I get in the Console but I just need the x, y, z values...:

    Regards,
    Carlos
     
    Last edited: Jan 2, 2016
  15. sysameca

    sysameca

    Joined:
    Mar 2, 2013
    Posts:
    99
    Does JSON .Net have a parsing/building methods or it is only a serializer?
     
  16. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yes, you can use JObject.

    Code (csharp):
    1.  
    2. var obj = JObject.Parse(jsonString);
    3.  
    4. var fooValue = obj["fooValue"];
    5.  
    You can also construct new JObject and JArray objects and use them to build JSON without having a concrete model. The JObject.ToString() method will return the JSON representation of the data stored in the JObject.
     
  17. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    If you want just x, y and z, there is a custom converter in the /Extras folder. There are actually several, but the one you need in this case is the Vector3Converter which will only include the x, y and z values. If your Vector3 is a property on your class, you can add the [JsonConverter(typeof(Vector3Converter))] attribute to your property and it will use it automatically. If you just want to serialize a straight Vector3, you can use the overload of SerializeObject that takes a collection of converters:

    Code (csharp):
    1.  
    2. var converters = new JsonConverter [] { new Vector3Converter() };
    3.  
    4. Vector3 pPosition = thePlayerTransform.position;
    5. //Use overload that takes converters
    6. string myPlayerSerializedData=JsonConvert.SerializeObject(pPosition, converters);
    7.  
    8. var myPlayerDeserializedData = JsonConvert.DeserializeObject(myPlayerSerializedData);
    9. Debug.Log(myPlayerDeserializedData);
    10.  
     
  18. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    This sounds like Unity has introduced possibly a new property that's not being accounted for in your GameObject serialization. Does it ever produce an error or it just completely hangs?

    Could you drop me an email:
    dustin (at) parentlement.com

    I definitely want to take a look at this one because this looks like a bug but I'm going to want to get some repro code from you so I can reproduce it.
     
  19. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
    Hello Dustin,

    I still have a problem when trying to deserialize the string back to Vector3.

    I should mention that after I serialize the Vector3 through Json, I convert the resulting string to bytes[] as so:

    Code (CSharp):
    1.  
    2. byte[]serializedSaveGameBytes = System.Text.Encoding.UTF8.GetBytes(myPlayerDat);//myPlayerDat is the serialized Json string in a different variable
    3.  
    in order to be able to save it in a Gaming Console.

    Now to load the data I convert the byte[] back to string as so:

    Code (CSharp):
    1.  
    2. playerSavedPositionString= System.Text.Encoding.UTF8.GetString(buffer);//buffer is the byte[]
    3.  
    and then I am trying to use Json to deserialize the string to a Vector3 and this is the code I am using based on your last answer.

    I would appreciate any help.

    Code (CSharp):
    1.  
    2.  
    3. void Start()
    4.     {
    5.         if(playerSavedPositionString != System.String.Empty)
    6.         {
    7.             pPosition = JsonConvert.DeserializeObject(playerSavedPositionString);// Here I get: error CS0266: Cannot implicitly convert type `object' to `UnityEngine.Vector3'. An explicit conversion exists (are you missing a cast?)
    8.  
    9. //If here I try adding a <Vector3> like so, "JsonConvert.DeserializeObject<Vector3>, I get a JIT error in the Gaming Console.
    10.  
    11.             DebugLogger.ShowMessage("\n1 From Start ObservePlayerPos... playerSavedPositionString: " + pPosition.ToString());
    12.  
    13.             thePlayerTransform.position = pPosition;
    14.         }
    15.         else
    16.         {
    17.             pPosition = thePlayerTransform.position;
    18.         }
    19.     }
    20.  
    21.  
    Regards,
    Carlos
     
  20. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
    Dustin,

    If on the other hand, the above is too convoluted to understand would you be kind enough to show me a quick example on how to:

    Take a Vector3 > Serialize with Json > Convert it back and forth to byte[] > and deserialize it back to a Vector3 with Json... without getting a JIT error

    Regards,
    Carlos
     
  21. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Ahh, this is for a console. Is it Xbox One? This is very frustrating because it's a bug we submitted to Unity a long time ago and they still haven't fixed it. I worked with the creators of The Long Dark on this particular bug. I don't know why Unity pukes but it only does so when trying to deserialize back to Unity specific structs like Vector2, Vector3, etc. Since you're doing this on a console and I have no control over when Unity will fix the issue. It was reported to them before E3 of last year I believe. Send me an email: dustin (at) parentelement.com and I'll send you updated converters that will fix the problem for you and work around the bug.

    Maybe @JoshPeterson could shed some light onto whether this bug will ever be fixed. I don't have the original bug number but it only happens with Unity structs.
     
  22. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
    Dustin,

    Thank you so much for your help. Yes it is for Xbox One unfortunately. I will send you an email so you can send me the fixed update. My email will be from Strongbox3d.

    Regards,
    Carlos
     
  23. cjmanca

    cjmanca

    Joined:
    Dec 6, 2013
    Posts:
    10
    While attempting to serialize a multidimensional array:

    Code (CSharp):
    1. DungeonRoom[,] rooms = new DungeonRoom[10, 10];
    2. [snip]
    3. JsonConvert.SerializeObject(rooms);
    I'm receiving a NullReferenceException with the following stack trace:

    Code (CSharp):
    1. at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeMultidimensionalArray (Newtonsoft.Json.JsonWriter writer, System.Array values, Newtonsoft.Json.Serialization.JsonArrayContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContract collectionContract) [0x00014] in E:\Documents\projects\Unity\Word Quest RPG\Source\Assets\libraries\JsonDotNet\Source\Serialization\JsonSerializerInternalWriter.cs:515
    2.   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue (Newtonsoft.Json.JsonWriter writer, System.Object value, Newtonsoft.Json.Serialization.JsonContract valueContract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContract collectionValueContract) [0x00159] in E:\Documents\projects\Unity\Word Quest RPG\Source\Assets\libraries\JsonDotNet\Source\Serialization\JsonSerializerInternalWriter.cs:151
    3.   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize (Newtonsoft.Json.JsonWriter jsonWriter, System.Object value) [0x00014] in E:\Documents\projects\Unity\Word Quest RPG\Source\Assets\libraries\JsonDotNet\Source\Serialization\JsonSerializerInternalWriter.cs:72
    4.   at Newtonsoft.Json.JsonSerializer.SerializeInternal (Newtonsoft.Json.JsonWriter jsonWriter, System.Object value) [0x00014] in E:\Documents\projects\Unity\Word Quest RPG\Source\Assets\libraries\JsonDotNet\Source\JsonSerializer.cs:454
    5.   at Newtonsoft.Json.JsonSerializer.Serialize (Newtonsoft.Json.JsonWriter jsonWriter, System.Object value) [0x00001] in E:\Documents\projects\Unity\Word Quest RPG\Source\Assets\libraries\JsonDotNet\Source\JsonSerializer.cs:446
    6.   at Newtonsoft.Json.JsonConvert.SerializeObject (System.Object value, Formatting formatting, Newtonsoft.Json.JsonSerializerSettings settings) [0x0002f] in E:\Documents\projects\Unity\Word Quest RPG\Source\Assets\libraries\JsonDotNet\Source\JsonConvert.cs:626
    7.   at Newtonsoft.Json.JsonConvert.SerializeObject (System.Object value) [0x00001] in E:\Documents\projects\Unity\Word Quest RPG\Source\Assets\libraries\JsonDotNet\Source\JsonConvert.cs:563
    8.   at SaveHelper.SaveDataFile[DungeonRoom[,]] (System.String fileName, com.LogicLace.WordQuest.Model.DungeonRoom[,] data) [0x00044] in E:\Documents\projects\Unity\Word Quest RPG\Source\Assets\utility\SaveHelper.cs:164
    In case your file has changed since the one I have (which is only a couple of weeks old), JsonSerializerInternalWriter.cs:515 is the following line:
    Code (CSharp):
    1. _serializeStack.Add(values);
    Do you have any insight as to why this would be happening?
     
    Last edited: Jan 6, 2016
  24. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Let me take a look. Either _serializeStack is null for some reason (the most likely cause) or something in the Add method is null. I'll take a look. I'm assuming DungeonRoom is a class, or is it a struct? Shouldn't make a difference, but just in case.
     
  25. cjmanca

    cjmanca

    Joined:
    Dec 6, 2013
    Posts:
    10
    It's a class. Also, I found that the multi-dimensional array serializes fine when placed inside another object. The bug only seems to crop up when attempting to serialize it directly.
     
  26. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Ok thanks, I'll dig into it.
     
  27. dnomn8r

    dnomn8r

    Joined:
    Nov 15, 2012
    Posts:
    12
    Hi Dustin, I've got a Unity project that's currently using the full JSON.NET library. I've been trying to get your Unity version of it integrated instead, mainly so I can use the .NET2.0 Subset setting. I've got it compiling and running, but it's having trouble with custom properties (deserializing enums with the use of a custom property), and also with primitives that come in as empty (which in our case, is a valid situation).

    The error I get is: Message: Error converting value "" to type 'System.Int32'.

    It works fine in the full JSON.NET library, so I was wondering if I'm using an incorrect JSONSerializerSetting(I've tried almost all the combinations though, and the same ones as the full library don't work), or if it's just not supported.

    Thanks.
     
  28. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Drop me an email and I'll take a look. Newer releases of JSON .NET that I'm not caught up with yet may have changed the processing of empty values. Technically it should be correct to get an error because in your case you have an empty string and are trying to convert it to an int.

    As to the Enums, I'm not sure what you mean by custom properties. But send me an email and we'll dig into it. Most likely we'll just need to write a couple of JsonConverters to work with your types to handle those special cases.
     
  29. Xylph

    Xylph

    Joined:
    Dec 11, 2013
    Posts:
    30
    Just hangs. This happens the 2nd time I launch the game (since there's no savefile to deserialize yet)

    Sure, I'll email you in a day or two. I'll build an isolated test scene first so it's easier to inspect.
     
  30. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    @Xylph Thanks. Does the game hang only in the editor or on the device as well?
     
  31. Xylph

    Xylph

    Joined:
    Dec 11, 2013
    Posts:
    30
    Only hangs on the device. It works in the editor (not including problem#2).

    Oh and what I meant by I wrote my own extension for serialization. It's just an interface which has the Serialize and Deserialize methods (IJsonSerializable). A script will implement this interface and they'll be automatically included in the json tree upon calling Serialize/Deserialize on the concerned GameObject.

    Sorry, I haven't started isolating the scene yet since I went out. I'll email you in a few days.
     
  32. Xylph

    Xylph

    Joined:
    Dec 11, 2013
    Posts:
    30
    @Dustin Horne Okay forget #2. I found the bug while I was isolating the code. Looks like my code clashed with my team's code. There was a sneaky exception (strange it wasn't being logged) being thrown during the loop (execution order bug).

    That still leaves #1 (hangs on mobile) though. I'll report as soon as possible.

    EDIT: I'll leave my JSON save file here for reference.
     

    Attached Files:

    Last edited: Jan 10, 2016
    Dustin-Horne likes this.
  33. cleromancer

    cleromancer

    Joined:
    Feb 3, 2015
    Posts:
    5
    Hi Dustin,

    My application for Windows Universal is still blocked on your plug-in. Your solution is great and I'd hate to have to swap it out, but I can't wait for the promised update much longer. When can I expect your fix to appear in the asset store?
     
    fantastisch_ likes this.
  34. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    @Xylph

    Thanks, got your email. I'm going to start digging in and see what might be causing the hang.

    @cleromancer , can you send me an email please? I'll send you an update to work with Windows Universal. I haven't published an update to the asset store yet because there are a couple of Unity bugs that are causing some issues for me and I'm trying to use as few "workarounds" as possible.
     
    cleromancer likes this.
  35. Xylph

    Xylph

    Joined:
    Dec 11, 2013
    Posts:
    30
  36. KimKaz

    KimKaz

    Joined:
    Dec 7, 2012
    Posts:
    7
    Hey Dustin, how are you?

    First, thanks for the wonderfull plugin! I Love it!
    I need to create a DLL from your asset to use in my internal DLL project, but when I try to generate it, I get these errors:



    My build's properties are:
     
  37. cleromancer

    cleromancer

    Joined:
    Feb 3, 2015
    Posts:
    5
    Thank you for the quick reply! I'll email you shortly.
     
  38. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    I'm not quite sure about your target framework there, but there is additional work that needs to be done. You'll need to generate multiple DLLs for different platforms. You can use one DLL for all IL2CPP platforms including Xbox One and PS4 but you'll need separate DLLs for Android (Mono), WinRT, Windows 10 Universal. You'll also need to set compiler directives in your project properties, such as UNITY_IOS which will produce an IL2CPP compatible DLL. What platform are you targeting? My email address is in the readme.txt file with the asset. Send me an email and I can send you precompiled binaries.
     
  39. vivalavida

    vivalavida

    Joined:
    Feb 26, 2014
    Posts:
    85
    hi @Dustin Horne is there a bson vector3 converter?
    I'm able to serialize-deserialize on if i use Json, but i need the data as a byte array and that's where things get problematic.

    Thanks.


    edit :
    i've been able to get this to work,
    i'm storing all my data in a list.

    Code (CSharp):
    1.  
    2.     List<ObjectModel> ListOfSavedObjects;
    3.     List<ObjectModel> deSerializedList;
    4.     byte[] serializedDataByteArray;
    5.     string serializedString;
    6.  
    7. ListOfSavedObjects = new List<ObjectModel>();
    8.         for (int i = 0; i < mySceneObjectsToBeSaved.Length; i++)
    9.         {
    10.             if (mySceneObjectsToBeSaved[i] != null)
    11.             {
    12.                 ListOfSavedObjects.Add
    13.                     (
    14.                         new ObjectModel
    15.                         {
    16.                             myObjectPosition = mySceneObjectsToBeSaved[i].transform.position,
    17.                             myObjectRotation = mySceneObjectsToBeSaved[i].transform.rotation.eulerAngles,
    18.                             myObjectActiveState = mySceneObjectsToBeSaved[i].activeSelf
    19.                         }
    20.                     );
    21.             }
    22.             else
    23.             {
    24.                 ListOfSavedObjects.Add(null);
    25.             }
    26.         }
    27.  
    28.         //json
    29.         var converters = new JsonConverter[]
    30.             {
    31.                 new Vector3Converter()
    32.             };
    33.            serializedJsonString = JsonConvert.SerializeObject(ListOfSavedObjects, Formatting.None, converters);
    34.  
    35.            serializedDataByteArray = System.Text.Encoding.UTF8.GetBytes(serializedJsonString);
    36.      
    37.            //now we deserialize
    38.            serializedString = System.Text.Encoding.UTF8.GetString(serializedDataByteArray);
    39.            deSerializedList = JsonConvert.DeserializeObject<List<ObjectModel>>(serializedString);
    40.            
    @strongbox3d
     
    Last edited: Jan 13, 2016
  40. cleromancer

    cleromancer

    Joined:
    Feb 3, 2015
    Posts:
    5
    Thank you again for the quick reply and special effort to get me a private build. Ultimately it didn't drop in as cleanly as I'd hoped, so I'm going to hold off on a Windows Store release until I can get the official asset through the Store, but I really appreciate the level of support you show for your plugin.
     
  41. cleromancer

    cleromancer

    Joined:
    Feb 3, 2015
    Posts:
    5
    I'm hitting a very specific bug trying to parse a valid DateTimeOffset, and the only workaround I've found requires making a code edit to JsonDotNet. It's a one-line change, so it's been a reasonable local workaround even when taking asset store updates, but in order to use pre-built JsonDotNet binaries it's time to seek a proper fix for this. Perhaps other people are trying to use DateTimeOffset and this could help them too.

    This is a JSON DateTimeOffset token that I'm getting from an out-of-the-box ASP.NET Web API: "2015-03-26T02:18:16.434107+00:00"

    In Mono, that value parses fine when using TryParse(String, out DateTimeOffset),
    but not the overload TryParse(String, IFormatProvider, DateTimeStyles, out DateTimeOffset).

    Unfortunately, it appears that JsonDotNet only uses the latter, and I haven't found any combination of CultureInfo or DateTimeStyle that will successfully parse that token. Also note that this appears to be an underlying Mono incompatibility and not a bug in JsonDotNet because I have no trouble parsing that value when using a native .NET compiler regardless of which overload I use. I believe that the more complicated Mono overloaded method is expecting an exact number of trailing digits. I'm able to get my example token to parse only after I've added an extra digit before the '+' sign (this is better explained by running example code I posted).

    Would you consider changing the default behavior or adding a runtime switch that would allow me to use the code path of the simpler TryParse method? If you can suggest a simple workaround that would allow me to use your pre-built binaries, that would be almost as good. I haven't explored the code to see what hooks there might be for fixing up the token on the way in, but since I believe it should already be considered a valid token, I think the best all-around fix would be to make sure the default behavior handles it as a valid token.

    This script illustrates the problem as a set of tests printed to the console.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Globalization;
    4. using System;
    5.  
    6. public class TestParse : MonoBehaviour
    7. {
    8.     int totalTests;
    9.     int totalSucceeded;
    10.     int totalFailed;
    11.  
    12.     private void Awake()
    13.     {
    14.         var tokens = new string[]
    15.         {
    16.             "2015-03-24T10:01:53.6974983+00:00", // SUCCEEDS
    17.             "2015-03-26T02:18:16.434107+00:00", // FAILS
    18.             "2015-03-26T02:18:16.4341070+00:00", // SUCCEEDS (padded with an extra zero)
    19.         };
    20.  
    21.         var cultures = new CultureInfo[]
    22.         {
    23.             null,
    24.             CultureInfo.InvariantCulture,
    25.             CultureInfo.CurrentCulture
    26.         };
    27.  
    28.         var styles = new DateTimeStyles[]
    29.         {
    30.             DateTimeStyles.None,
    31.             DateTimeStyles.AdjustToUniversal,
    32.             DateTimeStyles.AssumeLocal,
    33.             DateTimeStyles.AssumeUniversal,
    34.             DateTimeStyles.RoundtripKind
    35.         };
    36.  
    37.         foreach (var token in tokens)
    38.         {
    39.             foreach (var culture in cultures)
    40.             {
    41.                 foreach (var style in styles)
    42.                 {
    43.                     RunTests(token, culture, style);
    44.                 }
    45.             }
    46.         }
    47.  
    48.         Debug.Log(String.Format("Total tests: {0} (succeeded: {1}, failed: {2})", totalTests, totalSucceeded, totalFailed));
    49.     }
    50.  
    51.     private void RunTests(string token, CultureInfo culture, DateTimeStyles style)
    52.     {
    53.         DateTimeOffset dt;
    54.  
    55.         string test;
    56.         bool result;
    57.  
    58.         test = string.Format("DateTimeOffset.TryParse(\"{0}\", {1}, {2}, out dt)", token, (culture == null) ? "null" : culture.NativeName, style);
    59.         result = DateTimeOffset.TryParse(token, culture, style, out dt);
    60.         CountResult(test, result);
    61.  
    62.         test = string.Format("DateTimeOffset.TryParse(\"{0}\", out dt)", token);
    63.         result = DateTimeOffset.TryParse(token, out dt);
    64.         CountResult(test, result);
    65.     }
    66.  
    67.     private void CountResult(string test, bool result)
    68.     {
    69.         totalTests++;
    70.         if (result)
    71.         {
    72.             totalSucceeded++;
    73.         }
    74.         else
    75.         {
    76.             totalFailed++;
    77.         }
    78.  
    79.         Debug.Log(string.Format("{0} : {1}", (result) ? "    OK" : "FAILED!!!", test));
    80.     }
    81. }
    82.  
    83.  
    Thanks in advance for looking into it!
     
  42. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    I'll take a look. The IsoDateTimeConverter may fix this issue but I'll get a proper fix implemented. I'll also get you a new precompiled build that will drop into a new project and work.
     
  43. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    There's another possible workaround for you. Unfortunatlly, custom converters aren't supported for BSON, as they are a Json feature. However, I did some testing in a console application and found that you can accomplish it, but it's two hops because you have to deserialize to a JObject first so you can convert the Bson to Json. For my test I created a sample class called "Person" which I serialized using Bson, Then I deserialized that to a JObject, output the Json and deserialize that (and in your case you could them use converters).

    Code (csharp):
    1.  
    2. public class Person
    3. {
    4.    public string Name { get; set; }
    5.    public int Age { get; set; }
    6. }
    7.  
    Code (csharp):
    1.  
    2. static void Main(string[] args)
    3. {
    4.     //Serialize to BSON
    5.     var p = new Person { Name = "Chuck Norris", Age = 21 };
    6.  
    7.     var ms = new MemoryStream();
    8.    using (var writer = new BsonWriter(ms))
    9.    {
    10.         JsonSerializer serializer = new JsonSerializer();
    11.         serializer.Serialize(writer, p);
    12.    }
    13.  
    14.     var b64data = Convert.ToBase64String(ms.ToArray());
    15.     Console.WriteLine(b64data);
    16.  
    17.     //Deserialize to JObject
    18.  
    19.     byte[] data = Convert.FromBase64String(b64data);
    20.  
    21.     var ms2 = new MemoryStream(data);
    22.     using (var reader = new BsonReader(ms2))
    23.     {
    24.         var serializer2 = new JsonSerializer();
    25.  
    26.         var jo = serializer2.Deserialize<JObject>(reader);
    27.  
    28.         //JObject.ToString() gives you the JSON which you can then deserialize to your object
    29.         Console.WriteLine(jo.ToString());
    30.     }
    31.  
    32.     Console.ReadKey();
    33.  
    34. }
    35.  
     
  44. Sir-Thorgeir

    Sir-Thorgeir

    Joined:
    Jan 17, 2013
    Posts:
    16
    @Dustin Horne I am targeting tvOS with a project the uses your plugin. Out of the box the plugin runs into errors on device. Adding UNITY_TVOS everywhere UNITY_IOS is defined resolved them and it now works perfectly for me.

    Just wanted to let you know that it might be easy to add support for apple tv (tvOS).

    Code (CSharp):
    1. Just added the UNITY_TVOS:
    2. #if !(UNITY_IOS || ...
    3. becomes:
    4. #if !(UNITY_IOS || UNITY_TVOS || ...
     
    Dustin-Horne likes this.
  45. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yep, I've got it all setup in a beta release right now.
     
  46. henkjan

    henkjan

    Joined:
    Aug 1, 2013
    Posts:
    146
    Hi Dustin,

    We use Json.net for a while now and it worked fine!
    But now we have updated our project to Unity 5.3.1f1 and when running on iOS we get the following error:
    JsonSerializationException: Unable to find a constructor to use for type LHT.Framework.Network.VersionInfo. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.
    Newtonsoft.Json.Serialization.JsonPropertyCollection.GetClosestMatchProperty (System.String propertyName)

    ......

    The class VersionInfo is just a class with 2 string properties and lives in a separate assembly.
    There are no problems for web, Android, stand alone windows and stand alone macs. Only on iOS.

    Do you have any idea how I can fix this problem?

    UPDATE: Fixed it myself. I had to add link.xml because we use ill2cpp
     
    Last edited: Jan 15, 2016
    Dustin-Horne likes this.
  47. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yep, the stripping in IL2CPP gets more aggressive with every dot release and with IL2CPP, stripping is always enabled in some form. It's become a major headache for me because this is a question I get repeatedly and it's always sometime different. I did have one user point out that I can include an additional link.xml file which will be honored so I plan to do that for some of the built in types that occasionally get tripped and that I use such as TypeConverter.

    Another solution is to use a [Preserve] attribute. This works in code that you control, even if it's in a separate DLL. So you can create:
    Code (csharp):
    1.  
    2. public class PreserveAttribtue : Attribute
    3. {
    4.    public PreserveAttribute() {}
    5. }
    6.  
    It's just a marker so it can be empty. Then on any classes / methods (and constructors), or properties that are being stripped you jus add that [Preserve] attribute. The IL2CPP compiler will see that and it will not strip that particular element.

    There is no built in Preserve attribute. Unity just looks for the attribute with that name which is why you have to add it yourself. Just make sure you namespace it as I'll likely be including one (in a separate namespace) with my asset in the near future.
     
    henkjan likes this.
  48. MaT227

    MaT227

    Joined:
    Jul 3, 2012
    Posts:
    628
    Hi @Dustin Horne
    I am trying to use the classic json.NET 8.0.1 for .NET 2.0 dll with WebGL and I am experiencing a crash when doing code like this.

    Code (CSharp):
    1. var user = new { email = email, data = data}; // Those are strings
    2. JsonConvert.SerializeObject(user);
    I would like to know if the classic json.NET library is compatible with WebGL as it doesn't seem to even if I am not doing complicated things. That's why I am really interesting in your package but I have some questions concerning the available features.

    Here are some feature I am currently using :
    • DeserializeAnonymousType
    • [JsonObject(MemberSerialization.OptIn)]
    • [JsonProperty()]

    I think that every classic serialization is working on WebGL with your package but are the features above available ?
    If not, what do you suggest ?
    Thank you !
     
  49. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yes, the JsonObject attribute (and optin serialization) are supported, as well as JsonProperty. Anonymous types are not going to work for you though for a couple of reasons. One is that WebGL uses an AOT compilation method, on top of which Unity is running a .NET 3.5 equivalent so there is no support for dynamics.
     
  50. MaT227

    MaT227

    Joined:
    Jul 3, 2012
    Posts:
    628
    Dustin-Horne likes this.