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 Utility creates empty classes instead of null

Discussion in 'Scripting' started by Democide, May 15, 2017.

  1. Democide

    Democide

    Joined:
    Jan 29, 2013
    Posts:
    315
    So I'm working with JsonUtility and I just found out that if I have null references to classes, that after serializing (and deserializing) JsonUtility suddenly created references to empty classes. Which means that I need to add a SerializationCallbackReceiver and clean that up afterwards (which I can, but seems circumspect) and also trigger that serializationCallbackReceiverMethod after serializing.

    All of that seems really weird.

    Here's some dummy code that might help explain:

    Code (CSharp):
    1.  
    2.     public string GetSerializedState() {
    3.         var json = JsonUtility.ToJson(state);
    4.         state.OnAfterDeserialize();
    5.         return json;
    6.     }
    7.  
    8.     public void DeserializeState(string stateJson) {
    9.         state = JsonUtility.FromJson<GameState>(stateJson);
    10.     }
    11.  
    And in the GameState:

    Code (CSharp):
    1.  
    2.     public void OnBeforeSerialize() {
    3.         // Do nothing;
    4.     }
    5.  
    6.     public void OnAfterDeserialize() {
    7.         // Magic Cleanup code
    8.     }
    9.  
     
    ROBYER1 likes this.
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    JsonUtility uses Unity's serialization system in it's backend - so the same stuff that draws your stuff in the inspector. Just like the inspector, null serialized classes will get filled out with default values when you deserialize them.

    You can either keep doing what you're doing, or go for a different JSON library that allows you to specify what you want to do with empty values.
     
    Kiwasi likes this.
  3. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    if its some you don't want serialized (as is you always want it to be some default value when the object is loaded in) couldn't you simply use the [NonSerialized] attribute?
     
  4. Democide

    Democide

    Joined:
    Jan 29, 2013
    Posts:
    315
    Thing is, I want those serialized, but only if they are not null, which leads to the behavior described above. I'd use a different library but I heard that JsonUtility is the fastest by far, and probably remains so even if I have to clear out stuff afterwards. Since I'm using the deserialization in a simulation and I'll have to do lots of deserialization speed is importnat here..
     
  5. jwvanderbeck

    jwvanderbeck

    Joined:
    Dec 4, 2014
    Posts:
    825
    I'm having a similar annoyance with strings. null strings are being converted to empty strings upon calling ToJson, which is a huge issue because the API I cam connecting to treats a null parameter and an empty parameter as two very different things.
     
  6. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    JsonUtility definitely has some annoyances and limtations. If you can't get around it with the callback receiver you'll have to use a different library. There are lots available like JsonFX, JsonObject and of course my asset which is 40% off on the asset store at the moment.
     
  7. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    I get around this in several instances by simply checking if the deserialized variables are set to defaults. Nothing in game every actually uses the default values, for example an inventory slot with slotNumber -1. If a slot was just populated with data off the disk I check it to see if it's slotNumber is -1, then I simply set the whole slot to null.
     
  8. Democide

    Democide

    Joined:
    Jan 29, 2013
    Posts:
    315
    yeah, same here.
     
  9. whileBreak

    whileBreak

    Joined:
    Aug 28, 2014
    Posts:
    289
    Can you put the GameState class and an example of the json you are using?
     
  10. taxvi

    taxvi

    Joined:
    Feb 18, 2013
    Posts:
    30
    JsonObject is great. Thing is I have a weird fetish of keeping the number of 3rd party libraries to a minimum in my project. So, all hail the default values! ( I admit this is very unprofessional :D )
     
  11. copenhaverjf

    copenhaverjf

    Joined:
    Feb 15, 2017
    Posts:
    2
    Haha! I'm glad some people can relate to my misgivings of bundling 3rd party libraries!! I put out a question on the unity subreddit about a month back, and people came back and said "just use a 3rd party"... I'd like to keep my bloat to a minimum and only import the libraries I absolutely need, thx!

    Is there anywhere we can vote up issues on JsonUtility improvements? It seems like we're officially using JsonUtility as an anti-pattern... but I like the idea of using this as opposed to bundling an alternative.
     
    viseztrance and hyphenbash like this.
  12. earthcrosser

    earthcrosser

    Joined:
    Oct 13, 2010
    Posts:
    122
    I'd like to be able to upvote this as well. It seems like the consensus out there for REST is that if you don't want to send something then don't put it in the JSON body at all. So in my case I tried to send empty strings for some values and that gets an error back from the server. I'm trying to figure out how to use OnAfterDeserialize or OnBeforeSerialize to modify the json that the jsonutlity creates.... but I think I'm chasing a dead end.
     
  13. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    You can create a suggestion by hitting the "Feedback" link at the top of the page. Unity employees keep insisting that those gets read.
     
    olejuer likes this.
  14. earthcrosser

    earthcrosser

    Joined:
    Oct 13, 2010
    Posts:
    122
    Well I created a workaround that is good enough for my purposes, I thought I'd share it here. Suppose you have jsonString equal to: (string jsonString = JsonUtility.ToJson(foo,true))
    Code (CSharp):
    1. { "keyA": "a value",
    2. "keyB": "",
    3. "keyC": "another value"}
    4.  
    Here's a class that will remove "keyB" from the json
    Code (CSharp):
    1.  
    2. using System.Text.RegularExpressions;
    3. public static class JsonFormat {
    4.     public static string RemoveEmptyString(string jsonString)
    5.     {
    6.         string s = Regex.Replace(jsonString, "((\\\".*\\\")+(?=\\:))[:]\\s(\\\"\\\"[,\\r\\n])", string.Empty); //Find vales equal to "" and replace the key and value with empty string
    7.         s = Regex.Replace(s, @"^\s+$[\r\n]*", string.Empty, RegexOptions.Multiline); //Get rid of blank linkes
    8.         s = Regex.Replace(s, @"[,]+(?=\W*\})", string.Empty, RegexOptions.Multiline); //Get rid of any commas that might get left over at the end
    9.         return s;
    10.     }
    11. }
    12.  
    Then you should get
    Code (CSharp):
    1. { "keyA": "a value",
    2. "keyC": "another value"}
    3.  
    No more keyB!
     
    Last edited: Sep 4, 2018
    vonSchlank likes this.
  15. AndreiMarian

    AndreiMarian

    Joined:
    Jun 9, 2015
    Posts:
    77
    Any news on corrected JsonUtility?
     
  16. hyphenbash

    hyphenbash

    Joined:
    Dec 31, 2018
    Posts:
    20
    is there any performance implications that unity team don't apply this change for null values?
     
  17. AntonioNoack

    AntonioNoack

    Joined:
    Mar 26, 2020
    Posts:
    7
    #Bump, I want this as well
     
  18. olejuer

    olejuer

    Joined:
    Dec 1, 2014
    Posts:
    211
    I have been working with Newtonsoft.Json and it has been working like a charm. I found a repo that let's you add it as a package via the package manager, if that makes you less afraid of 3rd party libraries. https://github.com/jilleJr/Newtonsoft.Json-for-Unity
     
  19. Tom-Mensink

    Tom-Mensink

    Joined:
    Jul 27, 2017
    Posts:
    17
    It's a pitty this does not work together with UnityGltf, an important lib in many Unity projects, because UnityGltf uses the same dll, yet from a much older version. If anyone has a solution for that, then that would be very great