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. Lex_Dudya

    Lex_Dudya

    Joined:
    Feb 28, 2013
    Posts:
    29
    Here some code:
    Code (CSharp):
    1. public class JsonStringSerializer : IStringSerializer
    2.     {
    3.         /// <summary>
    4.         /// Serializes the specified object to a JSON string.
    5.         /// </summary>
    6.         /// <param name="value">The object to serialize.</param>
    7.         /// <returns>A JSON string representation of the object.</returns>
    8.         public string Serialize(object value)
    9.         {
    10.             return JsonConvert.SerializeObject(value);
    11.         }
    12.  
    13.         /// <summary>
    14.         /// Deserializes the JSON to the specified .NET type.
    15.         /// </summary>
    16.         /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
    17.         /// <param name="value">The JSON to deserialize.</param>
    18.         /// <returns>The deserialized object from the Json string.</returns>
    19.         public object Deserialize(string value, Type T)
    20.         {
    21.             //return JsonConvert.DeserializeObject(value, T);
    22.             return SerializationConverters.DeserializeObject(value,T);
    23.         }
    24.         /// <summary>
    25.         /// Deserializes the JSON to the specified .NET type.
    26.         /// </summary>
    27.         /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
    28.         /// <param name="value">The JSON to deserialize.</param>
    29.         /// <returns>The deserialized object from the Json string.</returns>
    30.         public object Deserialize(string value, Type T, JsonSerializerSettings settings)
    31.         {
    32.             return JsonConvert.DeserializeObject(value, T, settings);
    33.         }
    34.     }
    35.  
    Code (CSharp):
    1. public class SerializationConverters
    2. {
    3. public static object DeserializeObject(string str, Type T)
    4.     {
    5.         JsonSerializerSettings settings = new JsonSerializerSettings();
    6.         settings.TypeNameHandling = TypeNameHandling.All;
    7.         settings.NullValueHandling = NullValueHandling.Ignore;
    8.         settings.Converters.AddRange(Converters); // list of converter for custom types. One of this converters is IProduct converter                                                                                    
    9.    
    10.         object result = null;
    11.             result = JsonConvert.DeserializeObject(str, T, settings);
    12.         return result;
    13.     }
    14. }
    15. public class  ProductsDataConverter : JsonCreationConverter<IProduct>
    16.     {
    17.         protected override IProduct Create(Type objectType, JObject jObject)
    18.         {
    19.                 return new Product();
    20.         }
    21.     }
    22. public abstract class JsonCreationConverter<T> : JsonConverter
    23.     {
    24.         /// <summary>
    25.         /// Create an instance of objectType, based properties in the JSON object
    26.         /// </summary>
    27.         /// <param name="objectType">type of object expected</param>
    28.         /// <param name="jObject">
    29.         /// contents of JSON object that will be deserialized
    30.         /// </param>
    31.         /// <returns></returns>
    32.         protected abstract T Create(Type objectType, JObject jObject);
    33.         public override bool CanConvert(Type objectType)
    34.         {
    35.             return typeof (T).IsAssignableFrom(objectType);
    36.         }
    37.         public override object ReadJson(JsonReader reader,
    38.             Type objectType,
    39.             object existingValue,
    40.             JsonSerializer serializer)
    41.         {
    42.      
    43.      
    44.             JObject jObject = null;
    45.             if(reader.TokenType!= JsonToken.Null)
    46.                 jObject = JObject.Load(reader); // Load JObject from stream
    47.             else
    48.             {
    49.                 return null;
    50.             }
    51.             // Create target object based on JObject
    52.             T target = Create(objectType, jObject);
    53.             // Populate the object properties
    54.             serializer.Populate(jObject.CreateReader(), target);
    55.             return target;
    56.         }
    57.         public override void WriteJson(JsonWriter writer,
    58.             object value,
    59.             JsonSerializer serializer)
    60.         {
    61.             throw new NotImplementedException();
    62.         }
    63.         protected virtual bool isContainsProperty(JObject obj, string prop)
    64.         {
    65.             return obj[prop] != null;
    66.         }
    67.     }
    I use custom converter for this purpose. This code just simple example, i can't use TypeNameHandling.All becouse real code get JSON data from a custom server.
     
  2. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Ok, there is no need to use TypeNameHandling.All when deserializing if you don't / can't have to $type in your JSON because it won't work. It needs that JSON value to be able to work. I see that you're using a JObject it looks like and trying to populate your object... I wouldn't do that because there is a breaking IL2CPP bug right now that prevents bools from deserializing properly when using JObject. I am working on a bug report for Unity to address it. It's a problem with the way they share space between Bool and Byte for generics.

    Ok, so your converter actually looks pretty decent... it's smart. I would probably make one change. In your ReadJson method try:

    Code (csharp):
    1.  
    2. JsonConvert.PopulateObject(jObject.ToString(), target);
    3.  
    Give that a try once... If that doesn't work I'm going to have to step through and implement all of this so I can break down exactly what your converter is doing. I see that it's doing custom object creation which should be fine.

    Edit: Changed serializer.Populate to JsonConvert.PopulateObject.
     
  3. Lex_Dudya

    Lex_Dudya

    Joined:
    Feb 28, 2013
    Posts:
    29
    I've tried, and seems nothing changed. I got same error.
     
  4. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Hmm... ok well one more thing. Try my first suggestion and use Product instead of IProduct because you can't control the JSON and use TypeNameHandling. Change it to a List<Product> instead of a List<IProduct>. Then, nix your Create stuff altogether and just do:

    Code (csharp):
    1.  
    2. JsonConvert.DeserializeObject<ProductData>(jsonString);
    3.  
    I'll have to walk through and see what your code is doing but I have a feeling it has to do with trying to use the Interface for your base type and not being able to tell the deserializer what your concrete type is.

    Edit: ProductData should be the type to deserialize.
     
    Last edited: Jun 12, 2015
  5. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Could I also see the code for your Id class? I'm seeing types like Id<IProduct> for example. And look at your JSON string (it's in your screen capture). Every property is null... Are those all supposed to be null?
     
  6. Lex_Dudya

    Lex_Dudya

    Joined:
    Feb 28, 2013
    Posts:
    29
    Id class:
    Code (CSharp):
    1. using System;
    2. using Newtonsoft.Json;
    3. using UnityEngine;
    4.  
    5. namespace Assets.NanoLib.Utilities
    6. {
    7.     [Serializable]
    8.     [JsonObject]
    9.     public class Id<T>
    10.     {
    11.         [SerializeField]
    12.         [JsonProperty]
    13.         private int value = -1;
    14.  
    15.         public Id(int i)
    16.         {
    17.             value = i;
    18.         }
    19.  
    20.         public Id()
    21.         {
    22.             value = 0;
    23.         }
    24.  
    25.         [JsonIgnore]
    26.         public int Value
    27.         {
    28.             get { return value; }
    29.         }
    30.  
    31.         public static bool operator ==(Id<T> a, Id<T> b)
    32.         {
    33.             if ( ((object)a) == null)
    34.             {
    35.                 if (((object) b) == null)
    36.                 {
    37.                     return true;
    38.                 }
    39.                 else
    40.                 {
    41.                     return false;
    42.                 }
    43.             }
    44.             if (((object)b) == null)
    45.             {
    46.                 return false;
    47.             }
    48.             return a.value == b.value;
    49.         }
    50.  
    51.         public static bool operator !=(Id<T> a, Id<T> b)
    52.         {
    53.             if (((object)a) == null)
    54.             {
    55.                 if (((object)b) == null)
    56.                 {
    57.                     return false;
    58.                 }
    59.                 else
    60.                 {
    61.                     return true;
    62.                 }
    63.             }
    64.             if (((object)b) == null)
    65.             {
    66.                 return true;
    67.             }
    68.      
    69.             return a.value != b.value;
    70.         }
    71.  
    72.  
    73.         public override bool Equals(object obj)
    74.         {
    75.             Id<T> id = obj as Id<T>;
    76.             if (id != null)
    77.                 return id == this;
    78.             else
    79.                 return false;
    80.         }
    81.  
    82.         public override int GetHashCode()
    83.         {
    84.             return value.GetHashCode();
    85.         }
    86.  
    87.         public override string ToString()
    88.         {
    89.             var type = GetType();
    90.             if (type.IsGenericType)
    91.             {
    92.                 var genericArguments = type.GetGenericArguments();
    93.                 var s = "Id<" + genericArguments[0].Name + ">(" + value.ToString() + ")";
    94.                 return s;
    95.             }
    96.             else
    97.             {
    98.                 return type.Name + "(" + value.ToString() + ")";
    99.             }
    100.         }
    101.  
    102.      
    103.  
    104.  
    105.         public static implicit operator Id<T>(Int64 x)
    106.         {
    107.             return new Id<T>((int) x);
    108.         }
    109.  
    110.         public static implicit operator Id<T>(string x)
    111.         {
    112.             int result;
    113.             if (!int.TryParse(x, out result))
    114.             {
    115.                 throw new Exception("failed to parse id from string '"+x+"'");
    116.             };
    117.             return new Id<T>(result);
    118.         }
    119.     }
    120. }
    121.  
    real JSON data:
    Code (CSharp):
    1. {
    2.     "products": [
    3.         {
    4.             "id": {
    5.                 "value": 4
    6.             },
    7.             "name": "Meat",
    8.             "version_asset_android": 2,
    9.             "asset_android": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/eeaa5bf48c5461343bd532c3afad4806.",
    10.             "version_asset_ios": 6,
    11.             "asset_ios": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/c988696f0d83e21d5851cd2c861ed849.",
    12.             "version_asset_standalone": 1,
    13.             "asset_standalone": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/c1d71848390eb28999494d03fea0bd6e."
    14.         },
    15.         {
    16.             "id": {
    17.                 "value": 8
    18.             },
    19.             "name": "Goods2",
    20.             "version_asset_android": 1,
    21.             "asset_android": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/7aa8f0bd545637726cc4862f973a5409.",
    22.             "version_asset_ios": 4,
    23.             "asset_ios": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/a4ab9a588cf7048de9f35fdc45cb3845.",
    24.             "version_asset_standalone": 1,
    25.             "asset_standalone": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/f54f8924b9183f7c5f3967b3738704ad."
    26.         },
    27.         {
    28.             "id": {
    29.                 "value": 9
    30.             },
    31.             "name": "Goods3",
    32.             "version_asset_android": 2,
    33.             "asset_android": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/5cc6fae07d2214fcb9870dbcd9d51599.",
    34.             "version_asset_ios": 6,
    35.             "asset_ios": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/be540bb9277f2927578a638ff3e94357.",
    36.             "version_asset_standalone": 1,
    37.             "asset_standalone": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/334d6b839ac49e1385589c67e08fe6e9."
    38.         },
    39.         {
    40.             "id": {
    41.                 "value": 10
    42.             },
    43.             "name": "Goods4",
    44.             "version_asset_android": 1,
    45.             "asset_android": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/daee439bd22df9dd0144bd933c40f819.",
    46.             "version_asset_ios": 4,
    47.             "asset_ios": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/268da225ae0f3bb4557e927fa401092e.",
    48.             "version_asset_standalone": 1,
    49.             "asset_standalone": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/03af26a73392371d192b39f0bba03611."
    50.         },
    51.         {
    52.             "id": {
    53.                 "value": 11
    54.             },
    55.             "name": "Goods5",
    56.             "version_asset_android": 1,
    57.             "asset_android": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/6f707e3c8dec8b2de7df63a0616043e2.",
    58.             "version_asset_ios": 4,
    59.             "asset_ios": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/e4ceaa0360812fa73b2a7bf5d77e4b08.",
    60.             "version_asset_standalone": 1,
    61.             "asset_standalone": "http://nano-reality.projects.ilogos-ua.com/assets/bundles/product/850753c4ab65047dff030271f420adef."
    62.         }
    63.     ]
    64. }
    I got that error as with real json as well with test json with null fields
     
    Last edited: Jun 12, 2015
  7. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    I had a question for you. If I did a Preprocessor Define with a public variable that changes its type depending on the platform, will this break serialization/deserialization? Note the public variable is not a getter/setter.

    In my specific case, MovieTextures don't work in WebGL so my serialization object looks like this:
    Code (csharp):
    1. public class LoadedVideo
    2. {
    3.     private string fullLoadedString;
    4.     public string fileName;
    5.     public string extension;
    6.     public string fileNameWithExtension;
    7.     public string wallSide;
    8.     public VideoWallSide videoWallSideEnum;
    9.  
    10. #if UNITY_WEBGL
    11.     public WebGLMovieTexture movie;
    12. #else
    13.     public MovieTexture movie;
    14. #endif
    15. }
    And if it does break it, is there a recommended workaround?
     
  8. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Is WebGLMovie texture an actual type or one you made up to replace it with? You probably could get rid of the property completely if you're not using it in WebGL, it would just result in the property not being included in the json if you serialize from webgl and being ignored from the json when you deserialize.
     
  9. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    WebGLTexture is a custom type I made. Could you clarify what property you mean to remove?
     
    Last edited: Jun 12, 2015
  10. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    I mean you could just do:

    Code (csharp):
    1.  
    2. #if !UNITY_WEBGL
    3. public MovieTexture movie;
    4. #endif
    5.  
    As long as your code never tries to access the "movie" property when using WebGL then you don't even have to fake it out. Now let's say your JSON looks like this:

    Code (csharp):
    1.  
    2. {
    3.    "movie":{
    4.                     "id":4
    5.                  },
    6.     "name":"foo"
    7. }
    8.  
    When you deserialize that, if the "movie" property doesn't exist on your object, it just ignores it... so:
    Code (csharp):
    1.  
    2. JsonConvert.DeserializeObject<LoadedMovie>(jsonStrong);
    3.  
    Would result in the "name" property being populated but "movie" would be ignored if you're using WebGL because the property wouldn't even exist on the object. Does that make sense?
     
  11. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    That makes sense. But in my case I'm writing the code so that the calls to movie elsewhere in my code does the same thing no matter what type movie is MovieTexture or WebGLMovieTexture .
     
  12. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Oh then the way you're doing it is perfectly fine.
     
  13. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Ok, here's your issue I think. I think the stack trace might not be correct, but at any rate it cannot create your objects because it doesn't know what type to create. When it's attempting to populate your List it can't create the concrete implementation. The way you go about this as I said before is to use TypeNameHandling.All or TypeNameHandling.Auto. If you don't have that option then you have to do it with custom converters and such. In your case you have several interfaces being used though so you'd have to create custom converters for all of them individually.

    In this case, since you can't modify the json to include the $type parameter, the easiest solution is to switch to using the concrete implementation rather than the interface. If that's not an option you'll have to implement custom JsonConverters that are capable of constructing all of your objects that implement interfaces (even the ones with generic parameters like Id<T>)

    http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonConverter.htm
     
  14. Lex_Dudya

    Lex_Dudya

    Joined:
    Feb 28, 2013
    Posts:
    29
    Thank you, Dustin. I'll try these options
     
  15. Lex_Dudya

    Lex_Dudya

    Joined:
    Feb 28, 2013
    Posts:
    29
    Thanks Dastin. I've found the bug. The problem was not in interfaces, but in their inheritance, and wrong working of my Converters. I had two converters one for base interface, and other for child, so when deserializer was working, it calls first available converter in the list of converters. It calls converter of base interface, but should call child's converter.
     
  16. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Ahh that makes sense. You know, you can also get around that by putting the JsonConverter attribute straight on your classes / properties. For instance you have this let's say:

    Code (csharp):
    1.  
    2. public Id<Product> {get; set;}
    3.  
    You can do this:
    Code (csharp):
    1.  
    2. [JsonConverter(typeof(IdConverter<Product>))]
    3. public Id<Product> {get; set; }
    4.  
    So you can use generic converters and such that way as well and then you don't have to inject them when calling SerializeObject or DeserializeObject because they'll be automatically picked up from the attributes. Then Order shouldn't matter either.
     
  17. andymads

    andymads

    Joined:
    Jun 16, 2011
    Posts:
    1,614
    @Dustin Horne if you have json for an object like this:

    Code (CSharp):
    1. {
    2.     "number":1
    3. }
    and a class like this:

    Code (CSharp):
    1. public class Test
    2. {
    3.     public int num;
    4. }
    Is there an attribute to connect number with num when deserialising the json?

    Thanks.
     
  18. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yes, I cant recall off the top of my head whether it works with fields or only properties so you'll have to try, but add this attribute on top of your field there which will map it up both ways:

    Code (csharp):
    1.  
    2. [JsonProperty(Name="number")]
    3. public int num;
    4.  
     
  19. andymads

    andymads

    Joined:
    Jun 16, 2011
    Posts:
    1,614
    Thanks.

    It's actually PropertyName, not Name, but it turns out you can just pass the string directly into the constructor.
     
    Dustin-Horne likes this.
  20. m_wasim_bashir

    m_wasim_bashir

    Joined:
    Oct 2, 2012
    Posts:
    25
    i am having the same problem . its working on unity 4.6 smoothly but now i am unity it in unity 5.1 . it working unity editor but the problem on device. m using
    JSON .NET For Unity 1.4
    i updated Version: 1.5.0 (May 18, 2015) but still same problem.



    I/Unity﹕ NullReferenceException: Object reference not set to an instance of an object
    at System.Reflection.MonoProperty.CreateGetterDelegate (System.Reflection.MethodInfo method) [0x00000] in <filename unknown>:0
    at System.Reflection.MonoProperty.GetValue (System.Object obj, System.Object[] index) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.Utilities.ReflectionUtils.GetMemberValue (System.Reflection.MemberInfo member, System.Object target) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.Serialization.ReflectionValueProvider.GetValue (System.Object target) [0x00000] in <filename unknown>:0
    Rethrow as JsonSerializationException: Error getting value from 'data' on 'UserInfo'.
    at Newtonsoft.Json.Serialization.ReflectionValueProvider.GetValue (System.Object target) [0x00000] in <filename unknown>:0
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue (Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.JsonReader reader, System.Object target) [0x000
     
    Last edited: Jun 25, 2015
  21. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    @uwasimu - My email address is in the readme.txt file. Could you send me an email and show me what your JSON looks like and what the class looks like that you're deserializing to? I'm getting a sudden influx of bug reports around Unity 5.1 and 5.1.1. I'm not sure what changed but it seems to be breaking a bunch of stuff. :/ Also what platform are you targeting? I'm assuming iOS?
     
  22. SquaxShaun

    SquaxShaun

    Joined:
    Jun 22, 2009
    Posts:
    63
    Hi @Dustin Horne I'm having some trouble with model classes kept inside dlls when compiling for iOS using IL2CPP, when moving the test class into the project it is working as expected, on device we are getting the following exception:

    Code (CSharp):
    1.  
    2. ---
    3. -> applicationDidBecomeActive()
    4. Requesting Resolution: 750x1334
    5. Init: screen size 750x1334
    6. Initializing Metal device caps
    7. Initialize engine version: 5.1.1f1 (2046fc06d4d8)
    8. JsonSerializationException: Unable to find a constructor to use for type SerialisationTest.TestModel. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.
    9.   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateObject (Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, System.String id) [0x00000] in <filename unknown>:0
    10.   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.Object existingValue) [0x00000] in <filename unknown>:0
    11. ...
    It behaves as intended when using the Mono2x compiler option, but unfortunately we require IL2CPP to move forward.

    Any help is appreciated :)

    Regards,
     
  23. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Most likely IL2CPP is stripping the default constructor off of your test model. Have you tried putting it in your link.xml file to make sure it's not being stripped?
     
  24. kahong.chan

    kahong.chan

    Joined:
    Nov 22, 2013
    Posts:
    5
    Hi, I have purchase the asset yesterday. Nice job !
    But when I open the sample scene, there has a problem in it. It has a missing script in "ScriptHost" game object.
    How can I solve it ? Thanks.
     
  25. SquaxShaun

    SquaxShaun

    Joined:
    Jun 22, 2009
    Posts:
    63
    Thank you @Dustin Horne it was indeed stripping the constructor when placed inside a dll, adding the class namespace to link.xml resolved my issue; thanks again :D
     
    Dustin-Horne likes this.
  26. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yeah this seems to be an Editor bug that I haven't been able to fix. For some reason, just with my test scene, when I "publish" to the asset store it detaches that script. You'll want to attach the TextTest script to that missing component and it will work fine.
     
  27. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Good to know that worked. The stripping engine with 5.x seems to be much more aggressive. More specifically I'm seeing a lot of problems with Android in addition to IL2CPP platforms.
     
  28. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Good to know that worked. The stripping engine with 5.x seems to be much more aggressive. More specifically I'm seeing a lot of problems with Android in addition to IL2CPP platforms.
     
  29. billy-kahong-chan

    billy-kahong-chan

    Joined:
    May 23, 2014
    Posts:
    9
    Thanks Dustin Horne! It's work when I drag the script file to it.
     
    Dustin-Horne likes this.
  30. SimteractiveDev

    SimteractiveDev

    Joined:
    Jul 9, 2014
    Posts:
    97
    Hey, we recently purchased this and it works so far. There is one thing that does not appear to be working for us now when it was working with the original json.net library. That is serialising a DataTable to json. This worked great with the original library, but with this library it just returns the xml in the format:

    Code (CSharp):
    1.  { "XmlSchema":"xmldata"}.
    I know System.Data is not officially bundled with Unity, but you can easily add the dll to get the functionality, which is what we are doing for an editor plugin. Is there anyway to get this to work with your version, or at least be able to include the original json.net dll alongside this plugin without getting duplicate symbols error?

    Thanks, and great work on this!
     
  31. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    I'll need to take a look at this. I explicitly stripped all SQL Server stuff out of the port. In fact, I believe I stripped pretty much all System.Data related code as it wasn't officially supported. I could look at adding it back in but it'll definitely take some time and I'll have to set it up with a special define to enable it so it doesn't blow up for everyone that doesn't include System.Data in their project.
     
  32. SimteractiveDev

    SimteractiveDev

    Joined:
    Jul 9, 2014
    Posts:
    97
    I figured this would be the case and it very understandable. I just wanted to confirm my suspicions. Its not really a deal breaker for me. We just have a handy editor script to convert excel to json. There is no reason why I can't make this a separate app all together and separate it from unity. Thanks anyway!
     
  33. daklab

    daklab

    Joined:
    Nov 24, 2013
    Posts:
    27
    Are there any examples of how to deserialize a json file from the Resources folder?
     
    Dustin-Horne likes this.
  34. tosiabunio

    tosiabunio

    Joined:
    Jun 29, 2010
    Posts:
    115
    I hope sample from my code would help you:
    Code (CSharp):
    1.     private class ActorsRow {
    2.         public string NAME { get; set; }
    3.         public string MODEL { get; set; }
    4.         public string MATERIAL { get; set; }
    5.         public string ATTACHMENT { get; set; }
    6.         public float SPEED { get; set; }
    7.         public int RANDOM { get; set; }
    8.     }
    9.  
    10.     private List<ActorsRow> loadedActors;
    11.  
    12.     TextAsset json = Resources.Load("ActorsDB/ActorsDB") as TextAsset;
    13.     if (json == null) {
    14.         Debug.LogError("[People] Error loading ActorsDB JSON data");
    15.         return;
    16.     }
    17.     loadedActors = JsonConvert.DeserializeObject<List<ActorsRow>>(json.text);
    18.  
     
    Dustin-Horne likes this.
  35. daklab

    daklab

    Joined:
    Nov 24, 2013
    Posts:
    27
    Thanks for the quick reply! I could have swore that's how I tried it this morning. I'll give it a whirl when I get home.
     
    Dustin-Horne likes this.
  36. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    @tosiabunio Thanks for the reply!
    @daklab - I would do exactly as tosiabunion has, loading it as a text asset and then parsing if you're going to use the Resources folder.
     
  37. daklab

    daklab

    Joined:
    Nov 24, 2013
    Posts:
    27
    @tosiabunio @Dustin Horne Thanks again, works like a charm. My model was not correct and that is why it initially didn't work.
     
    Dustin-Horne likes this.
  38. sevensails

    sevensails

    Joined:
    Aug 22, 2013
    Posts:
    483
    Hi!

    This code does not works on Windows Phone.

    Code (csharp):
    1.  
    2.       FileStream stream = new FileStream(filename, FileMode.Create);
    3.         var serializer = new JsonSerializer();
    4.         using (var writer = new BsonWriter(stream))
    5.             serializer.Serialize(writer, _SaveGame);
    6.         stream.Close();
    7.  
    I got this error when saving :

    Code (csharp):
    1.  
    2. +        $exception    {System.IO.IOException: A concurrent or interleaved operation changed the state of the object, invalidating this operation. (Exception from HRESULT: 0x8000000C) ---> System.Exception: A concurrent or interleaved operation changed the state of the object, invalidating this operation. (Exception from HRESULT: 0x8000000C)
    3.    at Windows.Storage.Streams.FileRandomAccessStream.WriteAsync(IBuffer buffer)
    4.    at System.IO.FileStream.Write(Byte[] buffer, Int32 offset, Int32 count)
    5.    --- End of inner exception stack trace ---
    6.    at System.IO.FileStream.Write(Byte[] buffer, Int32 offset, Int32 count)
    7.    at System.IO.Stream.WriteByte(Byte value)
    8.    at System.IO.BinaryWriter.Write(Byte value)
    9.    at Newtonsoft.Json.Bson.BsonBinaryWriter.WriteString(String s, Int32 byteCount, Nullable`1 calculatedlengthPrefix)
    10.    at Newtonsoft.Json.Bson.BsonBinaryWriter.WriteTokenInternal(BsonToken t)
    11.    at Newtonsoft.Json.Bson.BsonBinaryWriter.WriteToken(BsonToken t)
    12.    at Newtonsoft.Json.Bson.BsonWriter.WriteEnd(JsonToken token)
    13.    at Newtonsoft.Json.JsonWriter.AutoCompleteClose(JsonContainerType type)
    14.    at Newtonsoft.Json.JsonWriter.InternalWriteEnd(JsonContainerType container)
    15.    at Newtonsoft.Json.JsonWriter.WriteEndObject()
    16.    at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
    17.    at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
    18.    at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
    19.    at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
    20.    at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value)
    21.    at GameSave.Save(Object _SaveGame)
    22.    at Main.Save()
    23.    at interfaceCreatePlayer.btOk_OnReleaseUIItem(tk2dUIItem obj)
    24.    at tk2dUIItem.Release()
    25.    at tk2dUIManager.CheckInputs()
    26.    at tk2dUIManager.Update()
    27.    at tk2dUIManager.$Invoke32(Int64 instance, Int64* args)
    28.    at UnityEngine.Internal.$MethodUtility.InvokeMethod(Int64 instance, Int64* args, IntPtr method)}    System.Exception {System.IO.IOException}
    29.  
     
  39. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Are you executing that code async like in a separate thread? This error is being thrown actually by Windows Phone. I don't think it's a JSON .NET bug but instead happens here:
    at Windows.Storage.Streams.FileRandomAccessStream.WriteAsync(IBuffer buffer)

    I'm not sure what exactly is calling that piece of code, it appears to be called from within the FileStream.Write method.
     
  40. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    You should also be using a "using" on your FileStream as it's an unmanaged resource and may not be getting diposed properly:

    Code (csharp):
    1.  
    2. using(var stream = new FileStream(filename, FileMode.Create))
    3. {
    4.         var serializer = new JsonSerializer();
    5.         using (var writer = new BsonWriter(stream))
    6.                 serializer.Serialize(writer, _SaveGame);
    7.  
    8.         stream.Close();
    9. }
    10.  
     
  41. sevensails

    sevensails

    Joined:
    Aug 22, 2013
    Posts:
    483
    Thanks for the support, but it still not working for me.

    I did try something else :

    Code (csharp):
    1.  
    2.      using (var stream = new MemoryStream())
    3.         {
    4.             var serializer = new JsonSerializer();
    5.             using (var writer = new BsonWriter(stream))
    6.                 serializer.Serialize(writer, _SaveGame);
    7.  
    8.             using (filestream = new FileStream(filename, FileMode.Create))
    9.             {
    10.                 stream.WriteTo(filestream);
    11.                 filestream.close;
    12.             }
    13.  
    14.  
    15.                 stream.Close();
    16.         }
    17.  
    But I still got this similar error :

    Code (csharp):
    1.  
    2. +        $exception    {System.IO.IOException: A concurrent or interleaved operation changed the state of the object, invalidating this operation. (Exception from HRESULT: 0x8000000C) ---> System.Exception: A concurrent or interleaved operation changed the state of the object, invalidating this operation. (Exception from HRESULT: 0x8000000C)
    3.    at Windows.Storage.Streams.FileRandomAccessStream.WriteAsync(IBuffer buffer)
    4.    at System.IO.FileStream.Write(Byte[] buffer, Int32 offset, Int32 count)
    5.    --- End of inner exception stack trace ---
    6.    at System.IO.FileStream.Write(Byte[] buffer, Int32 offset, Int32 count)
    7.    at System.IO.Stream.WriteByte(Byte value)
    8.    at System.IO.BinaryWriter.Write(SByte value)
    9.    at Newtonsoft.Json.Bson.BsonBinaryWriter.WriteTokenInternal(BsonToken t)
    10.    at Newtonsoft.Json.Bson.BsonBinaryWriter.WriteTokenInternal(BsonToken t)
    11.    at Newtonsoft.Json.Bson.BsonBinaryWriter.WriteToken(BsonToken t)
    12.    at Newtonsoft.Json.Bson.BsonWriter.WriteEnd(JsonToken token)
    13.    at Newtonsoft.Json.JsonWriter.AutoCompleteClose(JsonContainerType type)
    14.    at Newtonsoft.Json.JsonWriter.InternalWriteEnd(JsonContainerType container)
    15.    at Newtonsoft.Json.JsonWriter.WriteEndObject()
    16.    at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
    17.    at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
    18.    at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
    19.    at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
    20.    at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value)
    21.    at GameSave.Save(Object _SaveGame)
    22.    at Main.Save()
    23.    at interfaceCreatePlayer.btOk_OnReleaseUIItem(tk2dUIItem obj)
    24.    at tk2dUIItem.Release()
    25.    at tk2dUIManager.CheckInputs()
    26.    at tk2dUIManager.Update()
    27.    at tk2dUIManager.$Invoke32(Int64 instance, Int64* args)
    28.    at UnityEngine.Internal.$MethodUtility.InvokeMethod(Int64 instance, Int64* args, IntPtr method)}    System.Exception {System.IO.IOException}
    29.  

    Call Stack :

    Code (csharp):
    1.  
    2.     Assembly-CSharp.DLL!Newtonsoft.Json.Bson.BsonBinaryWriter.WriteTokenInternal(Newtonsoft.Json.Bson.BsonToken t) Line 78    C#
    3.     Assembly-CSharp.DLL!Newtonsoft.Json.Bson.BsonBinaryWriter.WriteTokenInternal(Newtonsoft.Json.Bson.BsonToken t) Line 75    C#
    4.     Assembly-CSharp.DLL!Newtonsoft.Json.Bson.BsonBinaryWriter.WriteToken(Newtonsoft.Json.Bson.BsonToken t) Line 65    C#
    5.     Assembly-CSharp.DLL!Newtonsoft.Json.Bson.BsonWriter.WriteEnd(Newtonsoft.Json.JsonToken token) Line 102    C#
    6.     Assembly-CSharp.DLL!Newtonsoft.Json.JsonWriter.AutoCompleteClose(Newtonsoft.Json.JsonContainerType type) Line 681    C#
    7.     Assembly-CSharp.DLL!Newtonsoft.Json.JsonWriter.InternalWriteEnd(Newtonsoft.Json.JsonContainerType container) Line 1438    C#
    8.     Assembly-CSharp.DLL!Newtonsoft.Json.JsonWriter.WriteEndObject() Line 362    C#
    9.     Assembly-CSharp.DLL!Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract collectionContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty) Line 398    C#
    10.     Assembly-CSharp.DLL!Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.Serialization.JsonContract valueContract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty) Line 129    C#
    11.     Assembly-CSharp.DLL!Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(Newtonsoft.Json.JsonWriter jsonWriter, object value, System.Type objectType) Line 64    C#
    12.     Assembly-CSharp.DLL!Newtonsoft.Json.JsonSerializer.SerializeInternal(Newtonsoft.Json.JsonWriter jsonWriter, object value, System.Type objectType) Line 847    C#
    13. >    Assembly-CSharp.DLL!Newtonsoft.Json.JsonSerializer.Serialize(Newtonsoft.Json.JsonWriter jsonWriter, object value) Line 784    C#
    14.  

    The origins is :

    Code (csharp):
    1.  
    2. using (var writer = new BsonWriter(stream))
    3.                 serializer.Serialize(writer, _SaveGame);
    4.  
    Maybe is a Unity bug?
     
  42. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    I'm not sure... would it be possible for you to put together a simple repro project for me? Looks like you're building a Universal App correct? I have a physical device I can test on. Basically it looks like something weird is going on with threading and two things are trying to access / write to the same stream. There's nothing multithreaded inside JSON .NET that you're using, but looking at the full call stack it looks like WinRT is treating every call as multithreaded and probably using an await in there.
     
  43. sevensails

    sevensails

    Joined:
    Aug 22, 2013
    Posts:
    483
    Strange... I cannot reproduce the bug on a New Project, even trying to save a similar class. I will try to investigage it further.
     
  44. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    I had a feeling that might be the case. Are you doing any of this inside a coroutine? Somehow something is trying to execute async and I'm not sure what or why.
     
  45. tbll

    tbll

    Joined:
    Jan 19, 2013
    Posts:
    31
    Hi Dustin,

    I am looking for a way to "not serialize" variables in a class like the [NonSerialized] do it with System Serialization.
    Can I do it with JsonDotNet ?

    Thanks,
    Thib
     
  46. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Yes, the attribute you want is [JsonIgnore]
     
    tbll likes this.
  47. Dustin-Horne

    Dustin-Horne

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

    I can't recall which all ones, but some of the standard XML serialization attributes are also honored, so if you already have the NonSerialized attribute, give it a try with that before you go and update all of your code. I just can't recall whether that particular attribute is honored or not.
     
  48. truffle_shuffle

    truffle_shuffle

    Joined:
    Dec 30, 2014
    Posts:
    16
    Just purchased. Errors on import. Not too sure what to do. I'm also using Full Inspector...not sure if that has anything to do with it or not.

    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>)'

    Assets/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>)'
     
  49. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Full Inspector includes the DLL version of Json .NET. You'll need to delete that DLL and then everything will work fine. I believe that either in the documentation for Full Inspector or on the Github page he has instructions that say where that dll is located.
     
  50. Enzign

    Enzign

    Joined:
    Aug 20, 2010
    Posts:
    169
    Hi Dustin, i'm having an issue with your great package. I'm trying to deserialize a class from some json data. These are the classes involved:

    public class ServerResponse
    {
    public ResponseStatus status;
    public string data;
    }

    public class ResponseStatus
    {
    public int id;
    public int code;
    public string message;
    public float timeTaken;
    public long serverTime;
    public string gameWorld;
    }

    and this is the json:

    {
    "status":{"id":0,"code":200,"message":"ok","serverTime":1438681779},
    "data":{"session_hash":"479efef48438c9c126d73733b0699fe26b387ab4e63dc626c23fc9e3c9d10","user":"127733"}
    }

    The problem here is that it can't seem to parse the "data"-part into a string. I want to do it like that and then parse the resulting json as another class later on.
    I tried litjson and then it could parse it as a string, and i'm guessing it's possible with your package as well somehow?