Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  2. Ever participated in one our Game Jams? Want pointers on your project? Our Evangelists will be available on Friday to give feedback. Come share your games with us!
    Dismiss Notice

JSON .NET for Unity

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

  1. Jack62Lewis

    Jack62Lewis

    Joined:
    Jun 17, 2013
    Posts:
    105
    Hi,

    I don't have any idea what this product is exactly but when I investigated saving lists to player prefs and discovered that only ints, floats and strings can be saved there and that if I wanted to save complex data in my game like transforms and lists and stuff I'd need something like this.
    So is that what i can do with this?

    Thanks,
    Jack
     
  2. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Among other things yes. It's a serialization asset so it'll take complex objects and convert them to json strings which you could then store in playerprefs if you wanted. Depending on what you're doing, what platform you're using and how much data it is, it might be better to write it to a file or push it to a web service, but writing it to PlayerPrefs works just fine.

    Here's an example of a "complex" object and a list and serializing it:

    Code (csharp):
    1.  
    2. public enum Gender
    3. {
    4.      Male = 0,
    5.      Female = 1
    6. }
    7.  
    8. public class Person
    9. {
    10.      public int Age { get; set; }
    11.      public string Name {get; set;}
    12.      public Gender Gender {get; set;}
    13. }
    14.  
    15. ///The code
    16. var jack = new Person {
    17.     Name = "Jack",
    18.     Age = 18,
    19.     Gender = Gender.Male
    20. };
    21.  
    22. var diane = new Person {
    23.     Name = "Diane",
    24.     Age = 18,
    25.     Gender = Gender.Female
    26. };
    27.  
    28. var people = new List<Person> { jack, diane };
    29.  
    30. var serialized = JsonConvert.SerializeObject(people);
    31.  
    32. //Now you have a string that looks like this that can be saved
    33. // [{"Name":"Jack", "Age":18, "Gender":0}, {"Name":"Diane", "Age":18, "Gender":1}]
    34.  
    35. //If you want gender spelled out you can use a StringEnumConverter
    36. public class Person
    37. {
    38.      public int Age { get; set; }
    39.      public string Name {get; set;}
    40.      [JsonConverter(typeof(StringEnumConverter))]
    41.      public Gender Gender {get; set;}
    42. }
    43.  
    44. //Now the serialized string would look like this
    45. // [{"Name":"Jack", "Age":18, "Gender":"Male"}, {"Name":"Diane", "Age":18, "Gender":"Female"}]
    46.  
    47. //To get it back to the List<Person> just do this:
    48.  
    49. var deserializedPeople = JsonConvert.DeserializeObject<List<People>>(serialized);
     
  3. Jack62Lewis

    Jack62Lewis

    Joined:
    Jun 17, 2013
    Posts:
    105
    Hi,

    Cool, thanks, that seems about what I'm looking for. So what type of variable is the 'serialized' var. Is that a string that can be saved to player prefs?

    So for example when the game is saved by the player I'd serialise a 'current item list' and set that to a play prefs string 'saved item list' then when the game is loaded by the player, I'd deserialise the 'saved item list' and set that to 'current item list' ?

    Thanks,
    Jack
     
  4. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Yes it's a string. :) So you can save it right to PlayerPrefs as a string if you want.
     
  5. Jack62Lewis

    Jack62Lewis

    Joined:
    Jun 17, 2013
    Posts:
    105
    Awesome thanks!
    So what other features is an asset like this used for? Is it a lot to do with storing information like this or is there more I'd be able to do that I'm not thinking about right now.

    EDIT: Also, is there another place I might save that string for save and loading things in my game. You mentioned putting it all in a file, is this recommended over playerprefs?

    Thanks,
    Jack
     
  6. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    It's all about data... transforming classes or collections or collections of classes, etc into a savable representation. There are some things to note... some types can be troublesome. You can't directly serialize and deserialize a MonoBehaviour / GameObject for instance, because there's no way to recreate it and Unity does some magic with it's == override. But you can do it by creating your own custom JsonConverters to use within Json .NET.

    Another widely used usage is for transferring stuff to Web Services. So if you're making a web request call and need to send data, you can serialize your data and send it... or take the response from a web service call and deserialize it back into a class object (or collection like List<T>, Array, Dictionary, etc) to use in your game.

    Unity has some built in Json serialization and deserialization now using it's JsonUtility class. It's much faster than JSON .NET because it's native and very simple, but that also makes it much more limited. It can't handle all of the complex types, for example can't handle Dictionaries where Json .NET can. Json .NET also allows you to create custom converters to change the way json is output and read.

    As for saving the data... there are lots of things you can do. You can send it to a web service using HTTP. Json is a standard format so it's really easy to handle by things like MVC WebApi. You can also save it to a file. In your case you're talking about having multiple save slots... I would actually recommend doing two pieces of serialization if you're going to use files. For example, have one class that represents your list of saves. Then each save is its own file. That way you're parsing way less data every time you load a save (or create a new one).
     
  7. Jack62Lewis

    Jack62Lewis

    Joined:
    Jun 17, 2013
    Posts:
    105
    Thank you for all this information.
    Yes, the multiple saving file system is what I'm looking for. I am slightly confused on what you mean exactly by files though. Is it that I have all my lists, ints, bools, strings that make up a player save and then I serialise them into an empty text file and create a list of these files (for each save created) and serialise this list again or am I way off? Could you describe an example scenario of how this might look maybe with some example code as well? Sorry for all these off topic questions that probably have more to do with basic coding than the asset itself!

    Jack
     
  8. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Well what I was essentially thinking was this... You have one class that has all of your save information in it for an individual save... so something like:

    Code (csharp):
    1.  
    2. public class GameSaveData
    3. {
    4.     public int PlayerHealth {get; set;}
    5.     public List<InventoryItem> InventoryItems {get; set;}
    6. }
    7.  
    Or whatever data you're saving... it can even be whole classes as properties... Then...

    Code (csharp):
    1.  
    2. public class GameSaveInfo
    3. {
    4.     public Guid GameSaveId {get; set;}
    5.     public DateTime SaveTime {get; set;}
    6.     public string Description {get; set;}
    7. }
    8.  
    So... GameSaveData is the data you're saving... GameSaveInfo is just metadata *about* the save. So then you have something like a file that contains all of the metadata. Call it GameSaves.json or whatever you want to call it... Then You can read the GameSaves.json file... if it's empty, do nothing... if it had data in it:

    Code (csharp):
    1.  
    2. var availableSaves = JsonConvert.DeserializeObject<List<GameSaveInfo>>(textFromGameSaves.json);
    3.  
    Then you can list all of those to load... now for saving...

    Code (csharp):
    1.  
    2. var saveData = new GameSaveData();
    3. var dataId = Guid.NewGuid();
    4.  
    5. saveData.PlayerHealth = 100;
    6. //populate the rest of saveData
    7.  
    8. var saveInfo = new GameSaveInfo();
    9. saveInfo.GameSaveId = dataId;
    10. saveInfo.SaveTime = DateTime.Now();
    11. saveInfo.Description = "Description of save - like current level or whatever";
    12.  
    13. availableSaves.Add(saveInfo);
    14. availableSaves = availableSaves.OrderByDescending(_ => _.SaveTime); //if you want newest first
    15.  
    16. var path = Path.Combine(Application.persistentDataPath, string.Format("{0}.json", dataId));
    17.  
    18.  
    19. System.IO.File.WriteAllText(savePath, JsonConvert.SerializeObject(saveData));
    20.  
    21. //Do similar to above but replace the GameSaves.json with JsonConvert.SerializeObject(availableSaves)
    22.  
    So basically what you're doing is loading the list of available saves....appending a new save to it... and saving the game data itself in a new file... the game data itself could be large but the metadata will be small. So you can load your List of saves from GameSaves.json... that you can present to the user. The reason we included "GameSaveId" is to give you a guid which is used to name the actual save file. So when you present the user the list of game saves... whichever one they select will tell you which file to read the save data from.
     
  9. Duffer123

    Duffer123

    Joined:
    May 24, 2015
    Posts:
    1,060
    Can some one post some code and indicate how you might serialise save out and loadin deserialise things like classes containing lists which hold sprites and audioclips and meshes etc. Can it?
     
  10. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    You'll have to be more specific and give a concrete example of what you're wanting to serialize. Unless there's a specific use case, I wouldn't serialize things like Audio clips and sprites or textures. You may want to save the state of those objects but not the binary data itself because you should already have it in your game.
     
  11. mkgame

    mkgame

    Joined:
    Feb 24, 2014
    Posts:
    591
    Hi,

    Do you have any examples for serializing and deserializing GameObjects and MonoBehavior instances? Am I have to implement for each my MonoBehavior classes a custom interface?

    I would like to save the whole scene and load it again. Do you have any example for that, or workflow? Do we have to iterate over all GameObjects, but then how do I know what GameObject should I create for my scripts, which are MonoBehavior classes, that's also not possible to serialize? I'm not familiar with JSON and the documentation handles too simple example/examples.

    An example project would be great, like this JSON asset does: https://www.assetstore.unity3d.com/en/#!/content/36879.

    I just don't know how to start. I must re-create GameObjects and I must be able to re-create MonoBehavior instances, I know they cannot be serialized on the fly, but what am I have to do?

    Thanks for your answer in advance!

    Note: I stuck with serializing a MonoBehavior derived class:

    Code (CSharp):
    1.  
    2.                 JsonSerializerSettings settings = new JsonSerializerSettings();
    3.                 settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    4.                 var jsonString = JsonConvert.SerializeObject(SerializeThis, settings);
    5.                 Debug.Log(jsonString);
    "NotSupportedException: rigidbody property has been deprecated
    UnityEngine.GameObject.get_rigidbody () (at C:/buildslave/unity/build/Runtime/Export/GameObject.deprecated.cs:23)"
     
  12. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    This is because JSON .NET uses reflection to resolve the properties. The rigidbody property (as well as some others) still exist on those objects but Unity throws a custom exception. It would also throw an exception even if it wasn't deprecated because JSON .NET would attempt to read a value from it to see if it was there and Unity threw a custom exception for that as well.

    There are two approaches you can take. The first approach would be to create a custom JsonConverter and ignore those properties. This would be a very heavy and tedious approach though because the components that were attached would need to have the same thing done and it would be hard to dynamically determine what all needs to be done.

    You also can't directly deserialize many of these objects because they don't have a default parameterless constructor. Again you'd have to add some additional constructor handling and/or implement a custom converter to deserialize them. The better approach is to create a Proxy, a class or set of classes that has all of the data you need to serialize on it, included any attached objects. You would then create new instances of those classes, populate their properties from the properties on your game object, and serialize that class instead.
     
  13. mkgame

    mkgame

    Joined:
    Feb 24, 2014
    Posts:
    591
    Thanks for your answer!

    Why do you not just try/catch around at reading the fields/attributes. Worked fine for me for copying MonoBehavior derived classes.

    Could you please show me with code a small proxy example for a class? (Or reference me to a site)

    I know by experience, that Transform should not copied by reflection without any restrictions. All GameObjects have a Transform component, so this seems to be the only why to re-create the GameObjects. How would you implement re-creating a GameObject? Maybe you have a better idea.
     
  14. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    A general try catch isn't a very elegant solution. It may hide legitimate errors, even if I were catching Unity specific exceptions, and I'd still need to know what those properties were so it would require a special converter, and it wouldn't solve the issue of recreating (deserialize) the object.

    I guess as an example you could have something like:

    Code (csharp):
    1.  
    2. public class SomeGameObjectProxy
    3. {
    4.     public Vector3 position {get; set;}
    5.     public Quaternion rotation {get; set;}
    6.    
    7.     //Whatever other data you'd need to save
    8. }
    9.  
    Then you just create a new instance of that proxy class, populate it's properties and return it. You could have every object you want to save return something like that if you need a collection of objects, then just use JsonConvert.SerializeObject on that object or collection. To recreate, you would use Instantiate (or maybe the objects are already in your scene) and then deserialize your save data back into objects and repopulate their properties.
     
  15. KeeLo

    KeeLo

    Joined:
    Nov 1, 2013
    Posts:
    76
    Hello! can you explain how to parse this json [["1",["value","value","value"]],["2",["value", "value","value"]],["3",["value","value","value"]]] to array or list... Thx
     
  16. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Code (csharp):
    1.  
    2. JsonConvert.DeserializeObject<List<Dictionary<int, List<string>>>>(yourJson);
    3.  
    That's some funky json there and I think unnecessarilly nested... you have an array of dictionaries of int/ string[]. You should think about restructuring that if you can.
     
  17. KeeLo

    KeeLo

    Joined:
    Nov 1, 2013
    Posts:
    76
    Thx... and what variable must be? or object which must be [serialized] ?
    public class PlayerInfo { public string Name { get; set; } public int Age { get; set; } public CharacterType Race { get; set; } }

    because
    string json = "[[\"1\",[\"value\", \"value\", \"value\"]],[\"2\",[\"value\", \"value\",\"value\"]],[\"3\",[\"value\",\"value\",\"value\"]]]";
    JsonConvert.DeserializeObject<List<Dictionary<int, List<string>>>>(json);

    generate this error

    JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Collections.Generic.Dictionary`2[System.Int32,System.Collections.Generic.List`1[System.String]]' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
    To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
    Path '[0]', line 1, position 2.
    Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureArrayContract (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract)
    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)
    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)
    Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList (IList list, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonArrayContract contract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, System.String id)
     
  18. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Oh shoot, I missed that those are not colons there. You're going to have work trouble with that because that's not valid json. are you creating it yourself or is it coming from somewhere else? what does the object look like that you want to store as json?
     
  19. Player7

    Player7

    Joined:
    Oct 21, 2015
    Posts:
    1,535
    Hi Dustin, did you ever do the Rect[] serializer? you said it was easy so I left it with you like month ago as I have no idea how to implement it, asking again as I'm actually going to need to use it pretty soon now.

    Also will newton json ever get something like messagepack (https://forum.unity3d.com/threads/free-messagepack-binary-and-json-text-serialization.408724/) like features? I must admit I like the newton json/bson for alot of all the additional features, attributes etc... but outside of that messagepack sure does look more useful for speed/size of data .. your thoughts?
     
  20. KeeLo

    KeeLo

    Joined:
    Nov 1, 2013
    Posts:
    76
    that i creating myself string json = "[[\"1\",[\"value\", \"value\", \"value\"]],[\"2\",[\"value\", \"value\",\"value\"]],[\"3\",[\"value\",\"value\",\"value\"]]]";

    but you can receive yourself http://alibek.eger.kz/api.php?client_id=101&action=13
    hm... in http://www.jsonschemavalidator.net/ my json is validated
     
  21. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    I apologize, I totally forgot! It's possibly I may entertain supporting MessagePack in the future but I'm not sure. I have to look deeper into how I could implement it. It would likely be a custom writer (just like the BsonWriter) so it could utilize the existing type and converter functionality but support the message pack format. I think MessagePack has some other limitations on types though and may be deterministic (again I have to look), and may also not support polymorphism.

    Here is the Rect converter. I haven't tested it but it should work. I'll be including it in my next update. I also have a bug fix for the Matrix4x4 converter (Values m10, m11, m12 and m13 weren't being serialized), and one other that I'm looking at so it'll be a bit before it gets released:

    Code (csharp):
    1.  
    2. using System;
    3. using Newtonsoft.Json.Linq;
    4. using Newtonsoft.Json.Shims;
    5. using UnityEngine;
    6.  
    7. namespace Newtonsoft.Json.Converters
    8. {
    9.     public class RectConverter : JsonConverter
    10.     {
    11.         public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    12.         {
    13.             if (value == null)
    14.             {
    15.                 writer.WriteNull();
    16.                 return;
    17.             }
    18.  
    19.             var m = (Rect)value;
    20.  
    21.             writer.WriteStartObject();
    22.  
    23.             writer.WritePropertyName("x");
    24.             writer.WriteValue(m.x);
    25.  
    26.             writer.WritePropertyName("y");
    27.             writer.WriteValue(m.y);
    28.  
    29.             writer.WritePropertyName("width");
    30.             writer.WriteValue(m.width);
    31.  
    32.             writer.WritePropertyName("height");
    33.             writer.WriteValue(m.height);
    34.  
    35.  
    36.             writer.WriteEnd();
    37.         }
    38.  
    39.         public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    40.         {
    41.             if (reader.TokenType == JsonToken.Null)
    42.                 return new Rect();
    43.  
    44.             var obj = JObject.Load(reader);
    45.             return new Rect((float) obj["x"], (float) obj["y"], (float) obj["width"], (float) obj["height"]);
    46.         }
    47.  
    48.         public override bool CanRead
    49.         {
    50.             get { return true; }
    51.         }
    52.  
    53.         public override bool CanConvert(Type objectType)
    54.         {
    55.             return objectType == typeof(Rect);
    56.         }
    57.     }
    58. }
    59.  
    In the next update you may run into an issue with it saying it multiple definitions, so you'll be able to remove this one once I release the update and include the new converter.
     
    Player7 likes this.
  22. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    That's what the validator says about the json coming back from your link.
    Here's what your JSON looks like formatted... you can see:
    Code (csharp):
    1.  
    2. Start Array ->
    3.    Start Array ->
    4.       Element[0]  = "1",
    5.       Element[1] = StartArray =>
    6.                   Element[1][0] = "value"
    7.                   Element[1][1] = "value"
    8.                   Element[1][2] = "value"
    9.            <= EndArray
    10.       <= End Array
    11.      ..repeat
    12.  
    13. <= End Array
    14.  
    So I need to know what you're trying to get at... you're trying to build an array with two different element types (an integer or string, and the second element being a whole other array).
     
  23. KeeLo

    KeeLo

    Joined:
    Nov 1, 2013
    Posts:
    76
    hm... what scheme did you choose? empty scheme from http://www.jsonschemavalidator.net/ ( No errors found. JSON validates against the schema )

    i'm trying to get menu of cocktails and i need to get list of elements for instantiate certain prefabs! every prefabs will take value from list... i need like public List<string> menu = new List<string>();
    string title = menu[0].name, string price =menu[0].price, string iconUrl = menu[0].iconUrl
    OR something like that
     
  24. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    You don't want to use a List<string> then... you'll want an object:

    Code (csharp):
    1.  
    2. public class MenuItem {
    3.     public string name;
    4.     public string iconUrl;
    5. }
    6.  
    Then your json would look like this:

    Code (csharp):
    1.  
    2. [{"name":"menu1", "iconUrl":"http://icon1.url"}, {"name":"menu2", "iconUrl":"http://icon2.url"}]
    3.  
    And you'd do:

    Code (csharp):
    1.  
    2. JsonConvert.DeserializeObject<List<MenuItem>>(json);
    3. //or
    4. JsonConvert.DeserializeObject<MenuItem[]>(json);
    5.  
     
  25. KeeLo

    KeeLo

    Joined:
    Nov 1, 2013
    Posts:
    76
    oh :((( ok can i use this json and do somethink like string title = Element[1][0] ??
     
  26. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    which json, my example or your original? You can use JObject.Parse on your original json and so it that way but it's all manual.
     
  27. KeeLo

    KeeLo

    Joined:
    Nov 1, 2013
    Posts:
    76
    Code (CSharp):
    1. Start Array ->
    2.    Start Array ->
    3.       Element[0]  = "1",
    4.       Element[1] = StartArray =>
    5.                   Element[1][0] = "value"
    6.                   Element[1][1] = "value"
    7.                   Element[1][2] = "value"
    8.            <= EndArray
    9.       <= End Array
    10.      ..repeat
    11. <= End Array
    Hello! Dustin... How you got this? ))) could you explain me?
     
  28. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Here's your JSON formatted:
    Code (csharp):
    1.  
    2. [
    3.     ["1", ["value", "value", "value"]],
    4.     ["2", ["value", "value", "value"]],
    5.     ["3", ["value", "value", "value"]]
    6. ]
    7.  
    The opening bracket "[" signifies the start of an array, and the closing bracket "]" is the end of an array. Curly braces "{" and "}" signify the start and end of an object (like a class or struct). Commas separate array elements and colons ":" separate properties.

    So you'll see above you have:

    Open Bracket, starts an array... each item in that array is also an array. Each of those arrays has a string value and another array in it... so:

    [ <-- start array
    ["1", ["value", "value", "value"]] <-- The array element is an array itself.

    So if we break down that first array item you have:

    "1" <-- a string
    ["value", "value", "value"] <-- an array of strings.
     
  29. yarune

    yarune

    Joined:
    Jun 23, 2015
    Posts:
    6
    Hi,

    I'm using JSON.Net for Unity and I'm getting a MissingMethodException just on my iPhone while calling JsonConvert.SerializeObject(object).

    Works in editor on PC, Mac en in Android builds. Am I missing something, like configuration, or could this still happen?

    I am assuming it should work on iDevices, it's the reason for me buying the plugin. :D

    Thanks in advance!
     
  30. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Could you show me the full stack trace? This happens when Unity strips something and IL2CPP always does some stripping. It's easy enough to fix with a Preserve attribute or a link.xml file, we just need to see what it is that's been stripped and the stack trace will hopefully show us that.
     
    yarune likes this.
  31. yarune

    yarune

    Joined:
    Jun 23, 2015
    Posts:
    6
    I'd be happy to. Thanks for your quick response.

    Code (CSharp):
    1.  
    2. MissingMethodException: Method not found: 'Default constructor not found...ctor() of System.ComponentModel.ReferenceConverter'.[/B]
    3.  
    4. [B]  at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00000] in <filename unknown>:0 [/B]
    5.  
    6. [B]  at Newtonsoft.Json.Serialization.JsonTypeReflector.GetTypeConverter (System.Type type) [0x00000] in <filename unknown>:0 [/B]
    7.  
    8. [B]  at Newtonsoft.Json.Utilities.ConvertUtils.GetConverter (System.Type t) [0x00000] in <filename unknown>:0 [/B]
    9.  
    10. [B]  at Newtonsoft.Json.Serialization.DefaultContractResolver.CanConvertToString (System.Type type) [0x00000] in <filename unknown>:0 [/B]
    11.  
    12. [B]  at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract (System.Type objectType) [0x00000] in <filename unknown>:0 [/B]
    13.  
    14. [B]  at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract (System.Type type) [0x00000] in <filename unknown>:0 [/B]
    15.  
    16. [B]  at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary (Newtonsoft.Json.JsonWriter writer, IDictionary values, Newtonsoft.Json.Serialization.JsonDictionaryContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract collectionContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty) [0x00000] in <filename unknown>:0 [/B]
    17.  
    18. [B]  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.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty) [0x00000] in <filename unknown>:0 [/B]
    19.  
    20. [B]  at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject (Newtonsoft.Json.JsonWriter writer, System.Object value, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract collectionContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty) [0x00000] in <filename unknown>:0 [/B]
    21.  
    22. [B]  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.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty) [0x00000] in <filename unknown>:0 [/B]
    23.  
    24. [B]  at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize (Newtonsoft.Json.JsonWriter jsonWriter, System.Object value, System.Type objectType) [0x00000] in <filename unknown>:0 [/B]
    25.  
    26. [B]  at Newtonsoft.Json.JsonSerializer.Serialize (Newtonsoft.Json.JsonWriter jsonWriter, System.Object value, System.Type objectType) [0x00000] in <filename unknown>:0 [/B]
    27.  
    28. [B]  at Newtonsoft.Json.JsonConvert.SerializeObjectInternal (System.Object value, System.Type type, Newtonsoft.Json.JsonSerializer jsonSerializer) [0x00000] in <filename unknown>:0 [/B]
    29.  
    30. [B]  at Newtonsoft.Json.JsonConvert.SerializeObject (System.Object value) [0x00000] in <filename unknown>:0
     
  32. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Got it... the constructor for ReferenceConverter is getting stripped.
    In the JsonDotNet folder you should find a link.xml file. It has an entry in it for TypeConverter. Replace the contents of the file with this:

    Code (csharp):
    1.  
    2. <?xml version="1.0" encoding="utf-8" ?>
    3. <linker>
    4.   <assembly fullname="System">
    5.     <type fullname="System.ComponentModel.TypeConverter" preserve="all" />
    6.     <type fullname="System.ComponentModel.ReferenceConverter" preserve="all" />
    7.     <!-- <namespace fullname="System.ComponentModel" preserve="all" /> -->
    8.   </assembly>
    9. </linker>
    10.  
    That'll add the ReferenceConverter and prevent it from being stripped. I've added this also to my source so the next update will have it included.
     
  33. yarune

    yarune

    Joined:
    Jun 23, 2015
    Posts:
    6
    Thanks! Works like a charm.
     
    Dustin-Horne likes this.
  34. Ryuuguu

    Ryuuguu

    Joined:
    Apr 14, 2007
    Posts:
    337
    Has deserialization been tested unity5.6 webGL?
    fixedData = JsonConvert.DeserializeObject<FixedData>(fixedDataText.text);​
    is giving an error
    ArgumentNullException: Argument cannot be null.
    Parameter name: method​
    only when running in webGL not in the editor. I have checked with a debug statement immediately before the offending call and the text passed in is not null. In fact if I pass a null parameter it produces a different error message.
    ArgumentNullException: Argument cannot be null.
    Parameter name: value​
    I will do more testing. I do not have this code available on 5.5 or earlier project so I don't know if thi really a new problem or not. I think it is a problem access the FixedData field types which included nested custom dictionaries.

    Cheers
    Grant
     
  35. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Thanks Grant, could you email me the code for the object you're trying to serialize so I can accurately reproduce it? I'm betting something is getting stripped by the webgl il2cpp compiler.
     
  36. Ryuuguu

    Ryuuguu

    Joined:
    Apr 14, 2007
    Posts:
    337
    I just pulled all references to " Inspectionary" (asset store asset) in the objects and that solve it.
    Thanks anyway.
     
    Dustin-Horne likes this.
  37. andymads

    andymads

    Joined:
    Jun 16, 2011
    Posts:
    1,495
    @Dustin-Horne should deserialization of an array of bools be supported on iOS? I've been having problems with an exception on device and have had to switch to an array of int.

    This is the message:

    ExecutionEngineException: Attempting to call method 'System.Collections.Generic.List`1[[System.Boolean, mscorlib, Version=2.0.5.0, Culture=, PublicKeyToken=7cec85d7bea7798e]]::.cctor' for which no ahead of time (AOT) code was generated.
     
  38. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Yes and I've seen this more often on Android. Unity's stripping is getting very frustrating. In your particular case it's the constructor for List<bool> that's been stripped.
     
  39. invadererik

    invadererik

    Joined:
    Oct 31, 2010
    Posts:
    126
    @Dustin-Horne , whats a good way to support, backwards/forwards compatibility with serialization?

    A simple example: I have a class with a health variable that was a float, and then later I change it to an int
    Next time I run the app, the serialization is going to throw an error. How do I deal with changes in types, etc?

    I have been straight up just using :
    string output = JsonConvert.SerializeObject(playerData);
    and
    PlayerData playerData = JsonConvert.DeserializeObject<PlayerData>( savedData );
     
  40. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    There's no automated way to support backwards and forwards conversion of data. It would be a manual process. You'd have to load the data and reserialize it. You could load the data in a JObject, remove the float value and replace it with the int value and reserialize it and it would work from that point forward.
     
  41. Jack62Lewis

    Jack62Lewis

    Joined:
    Jun 17, 2013
    Posts:
    105
    Just wanted to say thanks for the response! Apologies that it's been two months. When I can, I will be buying this and begin to test these things out.
     
    Dustin-Horne likes this.
  42. Glaswyll

    Glaswyll

    Joined:
    Feb 13, 2014
    Posts:
    94
    Thank you for making this! Worked great and integrated easily.
     
    Dustin-Horne likes this.
  43. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    You're both very welcome!
     
    Jack62Lewis likes this.
  44. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    258
    Hello @Dustin-Horne ! I'm having some problems on iOS (but not in Editor or on Android).

    I've got a struct declared in a .NET 3.5 DLL (more specifically I've ported the BigInteger class from .NET 4.5 and made it compatible with 3.5). Inside it, it has some public properties. Some just return a value and some call a method, see below:

    These gets serialized correctly (the only ones that actually 'work'):
    Code (CSharp):
    1. public bool IsZero { get { AssertValid(); return _sign == 0; } }
    2. public bool IsOne { get { AssertValid(); return _sign == 1 && _bits == null; } }
    These (among others) do not get serialized on iOS:
    Code (CSharp):
    1. public bool IsEven { get { AssertValid(); return _bits == null ? (_sign & 1) == 0 : (_bits[0] & 1) == 0; } }
    2. public string ValueAsString { get { return ToString(); } set { this = Parse(value); } }
    The only correlation I can see is that the ones which uses bit-operation or methods in their get/set-property doesn't get serialized. Do you know of this issue and do you have a solution/workaround for this?

    Thanks!
     
  45. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Yeah, I'm betting those properties aren't getting used in the code anywhere. Since Unity always does some stripping with IL2CPP, it's actually stripping those properties off of the object. In order to prevent that you'll either need to add a [Preserve] attribute to the class or add a link.xml file and add that class or namespace to it.
     
  46. Maisey

    Maisey

    Joined:
    Feb 17, 2014
    Posts:
    258
    Thanks a lot for your amazingly quick response! I will try it out and get back to you with my results.
     
  47. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    you're very welcome :)
     
  48. IvanVV

    IvanVV

    Joined:
    Apr 3, 2017
    Posts:
    1
    Hi, thank you for this beautiful asset!
    Do you have any plans on updating to latest version of Newtonsoft (10)?
     
    Dustin-Horne likes this.
  49. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,562
    Thanks! And I do, I'm just waiting for Unity 2017 to get out of beta before I start the process. Since Unity will be supporting an updated .NET profile, it means I can properly support types like BigInteger, etc so I'm waiting for that profile to be updated.
     
    jGate99 likes this.
  50. googlerOTS

    googlerOTS

    Joined:
    May 10, 2017
    Posts:
    5
    When are you planning to release update for Unity 2017 with .net 4.6 support?
     
unityunity