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
    pekalicious -

    Can you send me a PM with your Skype name? The property you're after is on JsonSerializerSettings and it's called PreserveReferenceHandling but, at least with Unity 3.5, it sometimes seems to just make the Editor crash with no error, just stops responding although I haven't tested it really heavily. I'd love to get on Skype with you and we'll see if we can get that doing what you're after.
     
  2. dl_studios

    dl_studios

    Joined:
    Oct 14, 2012
    Posts:
    76
    Just purchased. Looks like an awesome plugin.

    Somewhere I read that your plugin, JSON.NET for Unity, is compatible with Mongodb. I get that the bson format is compatible with Mongodb but from what I've read-- and tried-- it seems integrating the Mongodb c# drivers into Unity doesn't work too well given the current version of Mono 2.6.5 is not compatible with the Mongodb C# drivers. I've read that the drivers are only compatible with 2.10.1 +.

    Does your plugin somehow help with driver integration by letting us bypass the unsupported parts of the driver? Or does the phrase "compatible with Mongodb" simply mean that if you figure out how to get Mongodb to work with Unity, then you have the correct file format?

    Thanks.
     
  3. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Thanks. :) I don't know anything about MongoDB compatibility with Unity. Do you remember where you read it? I'd be interested to check it out. Now, it's likely that the base Newtonsoft library is compatible with MongoDBs BSON serialization and mine is just a port of that so in theory I'd think it should work just fine but I'm not sure about Mongo and Unity compatibility.
     
  4. fluidImages

    fluidImages

    Joined:
    Sep 27, 2013
    Posts:
    29
    Hey there..
    sorry for the question -
    just got the package - but - was wondering if I can do something like this:
    on a server, I put the following:
    and I have the following:

    and
    How would I get both the count of how many fluidTest Objects that I have as well as iterate through the Names?
    (in this example, I expect a count of 2 and the names being GatorThunder-2012-01 and GatorThunder-2012-02)
    Sean
     
    Last edited: Apr 9, 2014
  5. fluidImages

    fluidImages

    Joined:
    Sep 27, 2013
    Posts:
    29
    fixed my own issue:

    fluidTest[] newobject = JsonConvert.DeserializeObject<fluidTest[]>(www.data);
     
  6. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yep, you got it. And your JSON should be surrounded with [ ] in this case because it's an array.
     
  7. fluidImages

    fluidImages

    Joined:
    Sep 27, 2013
    Posts:
    29
    Dustin,

    It is, all is working well, thanks - saved some time!
     
  8. clever

    clever

    Joined:
    Oct 11, 2012
    Posts:
    39
    Hi there, got an error message when serializing/deserializing on a Windows Server 2012 (standard), it works fine when I run it from Editor on Win7 though... PLEASE HELP


    MissingMethodException: Method not found: 'Newtonsoft.Json.Serialization.JsonTypeReflector.GetAttribute'.

    Rethrow as TypeInitializationException: An exception was thrown by the type initializer for Newtonsoft.Json.Serialization.CachedAttributeGetter`1
    at Newtonsoft.Json.Serialization.JsonTypeReflector.GetJsonContainerAttribute (System.Type ࣅ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.Serialization.JsonTypeReflector.GetJsonObjectAttribute (System.Type ࢤ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract (System.Type ࡜) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract (System.Type ࣗ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.࠰ (System.Type ࢻ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ࡀ (Newtonsoft.Json.JsonReader ࡸ, System.Type ࣚ, Newtonsoft.Json.JsonConverter ࢬ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader ࣅ, System.Type ࢶ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader ࡞, System.Type ࢅ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader ࡃ, System.Type ࡡ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String ࠾, System.Type ࣮, Newtonsoft.Json.JsonSerializerSettings ࣔ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.JsonConvert.DeserializeObject[List`1] (System.String ࢻ, Newtonsoft.Json.JsonSerializerSettings ࣃ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.JsonConvert.DeserializeObject[List`1] (System.String ࡷ) [0x00000] in <filename unknown>:0

    at RoomManager.ࡃ () [0x00000] in <filename unknown>:0

    at RoomManager.OnGUI () [0x00000] in <filename unknown>:0



    ---

    serializing:

    MissingMethodException: Method not found: 'Newtonsoft.Json.Serialization.JsonTypeReflector.GetAttribute'.

    Rethrow as TypeInitializationException: An exception was thrown by the type initializer for Newtonsoft.Json.Serialization.CachedAttributeGetter`1
    at Newtonsoft.Json.Serialization.JsonTypeReflector.GetJsonContainerAttribute (System.Type ࣅ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.Serialization.JsonTypeReflector.GetJsonObjectAttribute (System.Type ࢤ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract (System.Type ࡜) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract (System.Type ࣗ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.࠰ (System.Type ࢻ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ࡀ (Newtonsoft.Json.JsonReader ࡸ, System.Type ࣚ, Newtonsoft.Json.JsonConverter ࢬ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader ࣅ, System.Type ࢶ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader ࡞, System.Type ࢅ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader ࡃ, System.Type ࡡ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String ࠾, System.Type ࣮, Newtonsoft.Json.JsonSerializerSettings ࣔ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.JsonConvert.DeserializeObject[List`1] (System.String ࢻ, Newtonsoft.Json.JsonSerializerSettings ࣃ) [0x00000] in <filename unknown>:0

    at Newtonsoft.Json.JsonConvert.DeserializeObject[List`1] (System.String ࡷ) [0x00000] in <filename unknown>:0

    at RoomManager.ࡃ () [0x00000] in <filename unknown>:0

    at RoomManager.OnGUI () [0x00000] in <filename unknown>:0
     
  9. andymads

    andymads

    Joined:
    Jun 16, 2011
    Posts:
    1,614
    Dustin I'm having an issue with BitArray.

    It serialises to JSON like this:

    "myBitArray":[false,false,false,false,false,false,false,false,false,false]

    But will not deserialise.

    I get this error:

    ArgumentException: Object type System.Collections.Generic.List`1[System.Object] cannot be converted to target type: System.Collections.BitArray
    Parameter name: val
     
  10. Dustin-Horne

    Dustin-Horne

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

    Does the standalone build work fine on Windows 7? I'm assuming you're creating a server backend which is why it's running on Windows Server 2012. Do you have the correct framework versions installed on the server? I haven't tried it on Windows Server 2012 so I'll have to fire up a VM and test it.

    @andy - could you share the code you're using to both serialize and deserialize? It *should* work but it's possibly that it doesn't handle bit as a primary type so it may have to be converted to / from int32 at serialization and deserialization time, in which case the values would be stored as 1 or 0. If your code looks good, I can throw together a custom convertor for you that will do those conversions.
     
  11. sevensails

    sevensails

    Joined:
    Aug 22, 2013
    Posts:
    483
    Sorry again, but I'm getting this error when running on Windows Phone 8.

    A first chance exception of type 'System.MissingMethodException' occurred in Assembly-CSharp.DLL
    Additional information: Method not found: 'System.TypeCode System.Type.GetTypeCode(System.Type)'.

    I know it will be fixed in next Unity Update, but there is a possible workaround for this?
     
  12. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    The only workaround Unity has been provided is here:

    http://forum.unity3d.com/threads/223065-Unity-4-3-3-Type-GetMembers(BindingFlags)-crash

    This is the same issue that causes GetTypeCode to be missing in JSON .NET. Following those instructions and copying WinRTLegacy.dll should fix the serialization problem. I'm still not sure why they didn't include the fix for that in a patch because it does break things (not just with my asset).
     
  13. andymads

    andymads

    Joined:
    Jun 16, 2011
    Posts:
    1,614
    Well I don't have the original code to hand but just tried knocking up a quick example and I now get a different error.

    Code (csharp):
    1.  
    2. public class BitArrayJsonTest : MonoBehaviour
    3. {
    4.     [System.Serializable]
    5.     public class Test
    6.     {
    7.         public BitArray bitArray = new BitArray(10);
    8.     }
    9.  
    10.     public Test test;
    11.  
    12.     void Start ()
    13.     {
    14.         string text = JsonConvert.SerializeObject(test);
    15.         Debug.Log(text);
    16.         test = JsonConvert.DeserializeObject<Test>(text);
    17.     }
    18. }
    19.  
    Code (csharp):
    1.  
    2. InvalidCastException: Cannot cast from source type to destination type.
    3. (wrapper dynamic-method) BitArrayJsonTest/Test.SetbitArray (object,object) <IL 0x00007, 0x00053>
    4. Newtonsoft.Json.Serialization.DynamicValueProvider.SetValue (object,object) (at Assets/JsonDotNet/Source/Serialization/DynamicValueProvider.cs:84)
    5. Rethrow as JsonSerializationException: Error setting value to 'bitArray' on 'BitArrayJsonTest+Test'.
    6. Newtonsoft.Json.Serialization.DynamicValueProvider.SetValue (System.Object target, System.Object value) (at Assets/JsonDotNet/Source/Serialization/DynamicValueProvider.cs:88)
    7. Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue (Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.JsonReader reader, System.Object target) (at Assets/JsonDotNet/Source/Serialization/JsonSerializerInternalReader.cs:572)
    8. Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject (System.Object newObject, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, System.String id) (at Assets/JsonDotNet/Source/Serialization/JsonSerializerInternalReader.cs:1090)
    9.  
    The json text looks like this:

    Code (csharp):
    1.  
    2. {"bitArray":[false,false,false,false,false,false,false,false,false,false]}
    3.  
     
  14. TedHoward

    TedHoward

    Joined:
    Nov 19, 2013
    Posts:
    21
    Finally tried it. I didn't quite work, but I saw where you were going so I fixed it locally.
    In RT_ReflectionUtils.cs RT_TypeExtensions.cs "bindingFlags" is sometimes a variable name, not a type name. Your search replace was too aggressive.
    You missed MemberTypes namespace'ing, too.

    -ted
     
  15. Dustin-Horne

    Dustin-Horne

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

    I'm working on a fix for BitArray. The problem is that it's basically its own collection type. It's not a generic collection and it's not an array... it is, but Type.IsArray returns false. The reason you got different errors is because in once case the BitArray property had been initialized so it was a cast issue... in the second instance it had to create it so it gave the creation error. I've fixed the creation error and now I'm working on the population piece.

    @Ted -

    I'll have to take another look at that patch and see what's going on with MemberTypes, thanks for pointing it out. The patch was based on a user submitted fix so I may have missed that when I put it together. I must have unchecked the case sensitive box when I did my replace to add the namespace.
     
  16. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    @Ted Andy -

    Here is an updated patch. This patches the WinRT issue and fixes BitArray support. One note, this patch did not fix BitArray for Windows Store Apps, just all other platforms. Unless someone absolutely needs the BitArray support for Windows Store Apps I'll be fixing that and including it in the next release version:

    www.parentelement.com/downloads/JSONNETPATCH_1_3_5_2.zip
     
  17. WalterKognito

    WalterKognito

    Joined:
    Dec 12, 2013
    Posts:
    11
    Does this support flash export? Or at the very least, do I have a prayer of modifying the source to make it flash compatible? My issue at the moment is minijson (which works on flash) chokes on some of my valid json, but jsonfx handles it fine (obviously doesn't work on flash though). $20 is definitely worth my time, but is json.net a feasible solution for my use case?
     
  18. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Unfortunately it does not... I hadn't actually tested Flash until today. It won't build for flash (999+ errors), primarily due to types not supported in Flash. You could try modifying it to work but I honestly don't think it would be worth your time. I would recommend trying Json Object if your json isn't terribly complex. It's free and would definitely be worth a try for Flash:

    Here is the asset store link: https://www.assetstore.unity3d.com/#/content/710
     
  19. sedlu

    sedlu

    Joined:
    Nov 12, 2012
    Posts:
    11
    Hi, I have purchased Json.Net for Unity for a while and it works perfectly, nice library!

    I am currently working on a PS3 project, which was originally developed as a PC game. We originally used Json.Net , but after we decided to change target platform to PS3, we encountered compilation problem caused by AOT compiling. Fortunately, your library saved us by simply replacing the original one.

    But now we are facing another severe problem about memory consumption. PS3 provides only 192MB for a custom process. We have tested that even a simple empty project uses about 50~60MB memory of PS3, and if System.dll is loaded, it consumes about 50MB more. Therefore, we are currently working on removing everything referencing System.dll, and found that Json.Net for Unity uses several types defined in System.ComponentModel which causes dependency to System.dll.

    Is there any way that I could try to remove the usage of System.ComponentModel? Any hint will be appreciated.


    p.s. I wrote some code to enable Json.Net for Unity supporting multi-dimensional array, which is needed by my project. These code was adapted from the original Json.Net. Although may not perfect, but if that helps you, I am glad to send it to you.
     
  20. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    sedlu -

    The multi-dimensional array code would be awesome and if you have paypal I'll issue you a full refund in trade. As for System.ComponentModel I've done some digging and it may be possible to remove it. Some of what it's used for is property change notification and some metadata resolution... it's also used for default values for properties but I may be able to work around that.

    Since I don't have access to PS3, could you do me a favor? Unity should output a debug symbol for PS3 builds. For instance, UNITY_EDITOR for running in editor, etc. Could you tell me what the symbol is that it adds for PS3? Once I have that I'll work on removing ComponentModel dependencies and get a test build ready for you.
     
  21. sedlu

    sedlu

    Joined:
    Nov 12, 2012
    Posts:
    11
    Hi,

    Thanks for reply. The debug symbol for PS3 is UNITY_PS3, just as the document said, no business secret :).

    I found there are still some other parts referencing System.dll. According to what I got from using monodis, they are:

    System.Text.RegularExpressions.Regex
    System.Text.RegularExpressions.RegexOptions
    System.Uri
    System.Collections.Generic.Stack
    System.Text.RegularExpressions.Match
    System.Text.RegularExpressions.Capture

    Because of the project schedule, I have to try to replace them with alternative types by myself. But I think if you try to do the same work, that will help this library to avoid dependence to System.dll, thus make it less weight.

    Thanks.
     
  22. chrisjjones

    chrisjjones

    Joined:
    Aug 4, 2012
    Posts:
    4
    Hi Dustin,

    Thank you so much for this great product. Your support for WinRT saved our bacon so to speak! The only issue I am having with the library is that it seems to fail when deserializing a Queue<T> data type. Is this something that could easily be added? It probably wouldn't be much trouble to just convert that to a List<T> on our side, but it would be great if it could work as is!

    Thanks,
    Chris
     
  23. Dustin-Horne

    Dustin-Horne

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

    Is it in Windows Store Apps that it's failing to deserialize the Queue<T>? I'll have to take a look... Doing some looking it looks like others have issues with Queue<T> on the official Newtonsoft version as well. I haven't started my conversion to Version 6 yet but I'll dig into the official code and see if there is any special handling for Queue<T> and see if I can't get it working but I'm not sure if official Newtonsoft supports Queue<T>.

    If you do decide to go the conversion route, I would go with an array probably over a list as it's lighter weight. Best bet is to do a custom ContractResolver that will handle the Queue<T> property conversion for you... let it be returned as an IList and then convert to Queue<T> in the resolver, then you don't have to change your class definitions.
     
  24. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    Hello,

    I'm serializing a Dictionary<Enum, Object>

    It works correctly but I don't want to convert the Enum to string, instead to its int values. By this way the final json would be much smaller.
    Could you suggest me the proper way to do it?

    Thanks,
    Maurizio
     
    Last edited: Apr 21, 2014
  25. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    mcmorry -

    It should serialize enums to their int value by default... Unless it's handling it differently for Dictionaries. I'll take a look today and see how it's serializing. If may be using the string value for dictionary keys. If it is, we could just create a simple ContractResolver to make sure it uses the int value instead.
     
  26. chrisjjones

    chrisjjones

    Joined:
    Aug 4, 2012
    Posts:
    4
    I have the platform set to Windows Store Apps and just creating a simple Queue<string> with a couple of elements fails to deserialize.

    Regarding your second suggestion, I was able to build a custom converter that is able to correctly deserialize our much more complex Queue<T>!

    Thanks,
    Chris

     
  27. Lordinarius

    Lordinarius

    Joined:
    Sep 3, 2012
    Posts:
    94
    Hi . Can i do text based serialization like this. In json .Net ? . I stucked when trying port my project to windows phone. Windows phone .Net library is not containing serialization.

    Code (csharp):
    1. FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
    2.         try
    3.         {
    4.  
    5.             BinaryFormatter formatter = new BinaryFormatter();
    6.             formatter.Serialize(fs, this);
    7.             success = true;
    8.         }
     
  28. andymads

    andymads

    Joined:
    Jun 16, 2011
    Posts:
    1,614
    I've just noticed this also. I've got a Dictionary<ENUM1,ENUM2> and the keys are serialised as strings not ints.
     
  29. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    Hi, any news? I was trying to understand more about the ContractResolver, but I can't figure out how to do it looking at your documentation.

    Thanks
     
  30. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    My apologies, I've been without internet for a few days (the city mowed over my fiber and cut my connection :/ ). My responses are below:

    @Lordinarius - kind of... it's a little different. You would use BSON and use JSON .NET to serialize using the BSON serializer instead of the BinaryFormatter.



    @andymads mcmorry - I'm still looking into this to figure out where that conversion happens and to see if I can change it to work otherwise or what the best solution is.
     
  31. TedHoward

    TedHoward

    Joined:
    Nov 19, 2013
    Posts:
    21
    TimeSpan.FromHours( 8 ) throws on iOS?!

    In JsonTextReader, I changed this:
    TimeSpan offset = TimeSpan.FromHours(hours) + TimeSpan.FromMinutes(minutes);
    to this:
    long ticks = (long)(TimeSpan.TicksPerMinute * (hours * 60.0 + minutes));
    TimeSpan offset = TimeSpan.FromTicks(ticks);

    I isolated the root cause to 'TimeSpan.FromHours( 8 )' throwing an OverflowException - should maybe be an argument out of range. So, that's clearly not your fault but there's the fix for at least one instance of this bug. iOS only from what I can tell.
     
  32. andymads

    andymads

    Joined:
    Jun 16, 2011
    Posts:
    1,614
    @Dustin, also just noticed that a Dictionary<int,ENUM> serialises with the keys as strings.
     
  33. Ghosthowl

    Ghosthowl

    Joined:
    Feb 2, 2014
    Posts:
    228
    Hi Dustin,

    I have a question about using this for saving. If I were to make a system that looks for all components in the scene (say inventories) what is the best way to go about serializing the data and deserializing it? I have currently a dictionary list that is made that gets all these inventories and assigns them unique ids. This is a dictionary<int, inventory> with inventory being a custom class. Inventory serializes and deserializes just fine, but if I try to serialize a dictionary, upon deserialization, it fails with:

    Code (csharp):
    1. JsonSerializationException: Cannot deserialize JSON array into type 'System.Collections.Generic.Dictionary`2[System.Int32,Inventory]'.
    I tried wrapping the dictionary in a serializable class but it yields:

    Code (csharp):
    1. JsonSerializationException: Cannot deserialize JSON array into type 'Inventories'.
    2. Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureArrayContract (System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract)
    How would I go about giving these objects unique IDs, serializing them all, then deserializing them and reassigning them. I have a feeling I am going about this the wrong way or doing something terribly wrong. BTW I am using Bson, perhaps using the JsonConverter to SerializeObject would work, but I would rather have the data in binary.

    Thank you for any and all insight.

    EDIT: I figured it out, it was this line that was causing the issues:

    Code (csharp):
    1. reader.ReadRootValueAsArray = true;
    I commented it out and now it works beautifully! Still my system is flawed, All my inventories are saving properly, but I need to figure out a way to keep the IDs to persist on the objects so their custom class components can hold the id's as well as compensate for instantiated objects of the same kind. Right now my system is only working because my look up of all the objects in my scene is the same every time. When this changes it will break. I'm too sleepy to think about it.:confused: I know it's something incredibly simple but I just can't think of it. Perhaps Sunday will prove a good thinking day for me.If anyone else has a good system for doing this, please do chime in :rolleyes:

    EDIT #2:

    Following the advice and very generous scripts of mweldon as seen here (http://forum.unity3d.com/threads/167991-Generate-unique-ID-on-object-creation) I have now used this to replace the interger system I had in place. Using system GUID, the objects now survive quitting of the editor and even reboots of the system. This will do very nicely. I am still open to other suggestions too for anyone who knows a better way of doing this. :smile:
     
    Last edited: May 5, 2014
  34. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    @Andy - I'm still working on it. I have several requests I'm working on at once and solidifying new features as well (multidimensional array support). I've been doing a bunch of research on how JSON .NET handles Enums in Dictionaries and the Key is by design that it is the string value and not the int value and in these instances TypeConverters for enums don't get evaluated, so I'm going to put together a typeconverter for Enums (which you'll need to modify for your specific enum type) which will accomplish the task for you.


    Awesome! Glad you got it figured out. That's exactly what I was going to suggest was using a GUID and making sure it stays the same for all of your objects. I'll take a look at the post you linked as well.
     
  35. andymads

    andymads

    Joined:
    Jun 16, 2011
    Posts:
    1,614
    @Dustin It's not a big issue for me so don't trouble yourself coming up with a custom solution. My code works as I want so I'm happy.
     
  36. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    I still need this feature. I'm serializing a lot of data. Using numbers I could reduce the size of files of more then 80%. Also these data will have to be sent to the client by http, so is quite important for me to optimize the size. If you need more time is fine. Just let me know your progress. Thank you.
     
  37. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    +1 for me also. Really need this.
     
  38. Ghosthowl

    Ghosthowl

    Joined:
    Feb 2, 2014
    Posts:
    228
    Hi Dustin,

    Another issue, not sure what is causing this but when I try to serialize a custom class I get this error:

    Code (csharp):
    1. MissingComponentException: There is no 'Rigidbody' attached to the "Blockman@Owner(Clone)" game object, but a script is trying to access it.
    2. You probably need to add a Rigidbody to the game object "Blockman@Owner(Clone)". Or your script needs to check if the component is attached before using it.
    3. UnityEngine.Rigidbody.get_velocity () (at C:/BuildAgent/work/d3d49558e4d408f4/artifacts/EditorGenerated/NewDynamics.cs:559)
    4. (wrapper dynamic-method) UnityEngine.Rigidbody.Getvelocity (object) <IL 0x00006, 0x00044>
    5. Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue (object) (at Assets/Imported/JsonDotNet/Source/Serialization/DynamicValueProvider.cs:102)
    6. Rethrow as JsonSerializationException: Error getting value from 'velocity' on 'UnityEngine.Rigidbody'.
    7. Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue (System.Object target) (at Assets/Imported/JsonDotNet/Source/Serialization/DynamicValueProvider.cs:106)
    8. 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.JsonContract collectionValueContract) (at Assets/Imported/JsonDotNet/Source/Serialization/JsonSerializerInternalWriter.cs:332)
    It is rather odd as I am not trying to serialize any rigidbodies. If I do add one for the sake of playing devils advocate, I get this error:

    Code (csharp):
    1. JsonSerializationException: Self referencing loop detected for type 'UnityEngine.Rigidbody'.
    2. Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference (System.Object value, Nullable`1 referenceLoopHandling, Newtonsoft.Json.Serialization.JsonContract contract) (at Assets/Imported/JsonDotNet/Source/Serialization/JsonSerializerInternalWriter.cs:232)
    3. Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.WriteMemberInfoProperty (Newtonsoft.Json.JsonWriter writer, System.Object memberValue, Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.Serialization.JsonContract contract) (at Assets/Imported/JsonDotNet/Source/Serialization/JsonSerializerInternalWriter.cs:209)
    4. 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.JsonContract collectionValueContract) (at Assets/Imported/JsonDotNet/Source/Serialization/JsonSerializerInternalWriter.cs:335)
    I have tried both the regular serialization and the BSON methods and they both yield the same results.

    EDIT: Nevermind I fixed the issue. Seems something on the class was referencing a gameObject - which was causing the error. I got a custom contract resolver going that ignores both individual properties and as well as types from here (http://stackoverflow.com/a/14510134) [HUGE THANKS to drzaus] In order to get this to work for this version of JSON you need to change the line:

    Code (csharp):
    1.         if (this.IsIgnored(property.DeclaringType, property.PropertyName)
    2.         || this.IsIgnored(property.DeclaringType.BaseType, property.PropertyName))
    to this:

    Code (csharp):
    1.         if (this.IsIgnored(property.PropertyType, property.PropertyName)
    2.         || this.IsIgnored(property.PropertyType.BaseType, property.PropertyName))
    Also you need to have the following in your file:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System;
    5. using System.Linq.Expressions; //This is used if you add Steve Rukuts' lamba method just below the post I linked
    6. using System.Reflection;
    7. using Newtonsoft.Json.Serialization;
    8. using Newtonsoft.Json;
    You need to do this because the original code is using a JSON.NET 6.0 feature that isn't available to us yet. It still works the same way however using this.

    Now I can just select what bits and pieces of the classes to serialize without having to make a new class or edit the class. Really need something like this to have from the get go, would have made things a ton easier!:mrgreen:
     
    Last edited: May 8, 2014
  39. Afif-Faris

    Afif-Faris

    Joined:
    Oct 11, 2013
    Posts:
    16
    Hi Dustin,

    Currently I am converting all game data from xml to json, but I have a problem that unity crash when serializing certain xml in my game.
    After two days of frustration finding the cause, I found it.

    The crash happen when serializing Color data type with value other than 0 or 1. ( 0.2f or 2 will crash).

    Didn't crash (0 or 1)
    Code (csharp):
    1. "Colorr":{"r":0.0,"g":0.0,"b":0.0,"a":0.0,"grayscale":0.0}
    2. "Colorr":{"r":1.0,"g":1.0,"b":1.0,"a":1.0,"grayscale":0.0}
    Crash (between 0 - 1)
    Code (csharp):
    1. "Colorr":{"r":0.4,"g":0.3,"b":0.2,"a":0.2,"grayscale":0.0}
    I try to change the value using text editor
    Code (csharp):
    1. "Colorr":{"r":0.4,"g":0.3,"b":0.2,"a":0.2,"grayscale":0.0}
    and deserialize it. It works. The crash only happen when serializing not deserializing.

    Can you fix this please??? :(

    I've included test project in the attachment so you can test it right away. ;)
    "Test1" scene can serialize black (rgb = 0)
    "Test2" scene will crash when serializing the color with value between (0-255)


    And according to this post..
    We can serialize only the data we need using custom ContractResolver. I've tried this but no luck... I can't really understand how to implement it I am a noob programmer :(

    Would you mind to modify the project in the attachment to implement it?? Sorry to bother you.

    I need the data to be like this
    Code (csharp):
    1. {"Colorr":{"r":1.0,"g":0.0,"b":0.0,"a":1.0},
    2. "Vectorr":{"x":15.0,"y":2.0,"z":6.0}
    instead of this
    Code (csharp):
    1. {"Colorr":{"r":1.0,"g":0.0,"b":0.0,"a":1.0,"grayscale":0.299,"gamma":{"r":0.99999994,"g":0.0,"b":0.0,"a":1.0,"grayscale":0.298999965}},
    2. "Vectorr":{"x":15.0,"y":2.0,"z":6.0,"normalized":{"x":0.9214427,"y":0.122859031,"z":0.3685771,"magnitude":1.0,"sqrMagnitude":1.0},"magnitude":16.27882,"sqrMagnitude":265.0}}
    Thank you.
     

    Attached Files:

  40. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Ohh jeez, I see I have a couple more messages here that I didn't see notifications for. I can take a look Afif but it's going to take some time. I'll take a look at your package and see if there's something obvious (like whether you're using Color vs Color32). I am in the process of testing multiple other changes that will go into the next release. Multidimensional Array support, another place where GetEnumerator with arrays of structs was occasionally returning System.String on iOS (Mono Bug, but workaround put in place), and a temporary fix for doing serialization in Editor Extensions. For some reason the Unity editor crashes without warning or error (just closes) when it uses reflection to try to find Serialization callbacks on editor objects. It also includes the updates for the changes Unity make that broke the asset in Windows Store Apps (the previous patch fixed this as well).

    I also need to figure out whether it's possible to serialize enum keys in dictionaries as int rather than string as those requests came in awhile ago but I've had to keep them on the backburner to make sure bugs were addressed so I have a lot on my plate and bugs have to take immediate priority when/if they come in, but I can certainly take a look at this and figure out what's crashing.
     
  41. Afif-Faris

    Afif-Faris

    Joined:
    Oct 11, 2013
    Posts:
    16
    Oh I am sorry if I bother you. Its ok, take your time. I can do other things first.
    Its the same either I use Color32 or Color data type.
     
  42. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Oh no, it's not a bother at all. I just have to prioritize and want to make sure expectations are realistic.
     
  43. zlSimon

    zlSimon

    Joined:
    Apr 11, 2013
    Posts:
    31
    Hi Dustin,
    I was using the Json.net dll which gave me aot errors on IOS but worked fine on android. With your plugin I hadn't had to change any code and it worked like a charm on IOS. However now I get an error on Android when starting the app:

    JsonSerializationException: Could not load assembly 'mscorlib'.

    I tried all stripping levels without any success.
    I am using Unity 4.2

    I really hope that you can help me.

    Simon
     
  44. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Sure Simon. We'll continue the conversation we have in Email so I can get a repro if possible and I'll report back here if there is an issue found and fixed with the asset.
     
  45. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    Hello, any ETA for the Dictionary<Enum, T> problem? It starts to be urgent for me to resolve it.
     
  46. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    I'll try to get it wrapped up in the next couple days. I've completed testing and need to clean up a bit of code for my next release and then I'll take a look at it. It's not actually a bug. Dictionary keys are treated as strings so that valid JSON can be produced, this is why the Enums are treated as strings and the converters don't run for the enums. I actually have to write a custom JsonConverter for you as an example and the converter will have to handle the Dictionary itself, not just the Enum.

    If this is something you need immediately, here is an example of a solution for the Dictionary converter. In your case you'll want to cast the enum value to an int:

    http://stackoverflow.com/questions/6845364/json-net-specify-converter-for-dictionary-keys

    Edit: This example shows reading JSON and creating the dictionary... in your case you'll want CanWrite to be true and implement WriteJson instead of the ReadJson bit. You'll want to do the conversion there.
     
  47. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    Actually I need to serialize and also deserialize. Seams easy to change the code for the deserialization. First I should create a Dictionary<int, MyType> to be used for the deserialization and then copy the values to the final Dictionary<MyEnum, MyType>. Do you confirm?

    I suppose that I should I do something similar for the serialization. Copy my data into a Dictionary<int, MyType> and then populate with that the serializer. Is it correct?

    Also is important to say that I need this for mobile. Will it it work on iOS? I read that sometime there are some problems with reflection methods.

    Thank you.
     
  48. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yes you could do it that way, or create the Dictionary<MyEnum, MyType> and when you read the int JSON value just cast it using (MyEnum) and then populate the dictionary entry.

    And yes this works for iOS, Android, Windows Phone and Windows Store Apps as well. There is a patch for Windows Store Apps. Also, Unity introduced a bug for Windows Phone so you'll have to use a workaround if you're using Unity 4.3.3 or 4.3.4 by copying a DLL for Unity 4.5 (this was how Unity said to fix it).

    There is one iOS bug outstanding that you might run into but probably won't where you get the System.String does not implement IEnumerator error. If you do, send me a message and I'll get you a patch. It will be fixed in the next release.

    Also, since Unity fixed the GetEnumerator bug I'm making some changes that will improve performance on iOS for Unity 4.5+.
     
  49. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    I'm not sure if I'm understanding correctly. To deserialize and to serialize should I still create an intermediateDictionary? If not, where I should do the cast if not in the foreach?
    How should I read the JSON data without deserializing it into a intermediateDictionary?
     
  50. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Oh I see what you're saying and I misunderstood about the reflection as well. Yeah you'll wanted to avoid doing it that way exactly. In your case, create a JsonConverter for your specific dictionary type (i.e. Dictionary<MyEnum, String>) and if you have more than one dictionary, create a separate converter for each one. Then inside your WriteJson and ReadJson methods you can make the intermediate dictionary the type that the converter handles instead of using reflection to create it.