Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

JSON serialization.Why doesn't it work out of the box?

Discussion in 'Scripting' started by undefined666, Sep 23, 2018.

  1. undefined666

    undefined666

    Joined:
    Apr 3, 2018
    Posts:
    53
    I have base class for holding data for server request:

    Code (CSharp):
    1. [System.Serializable]
    2. public class BaseRequest : System.Object {
    3.  
    4.     [System.Serializable]
    5.     public class UserData:System.Object {
    6.         public string access_token;
    7.         public string account_id = "test_001";
    8.         public string platform = "Facebook";
    9.     }
    10.     public UserData user;
    11.     //rest of the data
    12. }
    Then I serialize object of this class with JSONUtility
    string jsonStr = JsonUtility.ToJson(post.data);

    Although I didn't initialize 'user' field parser treats it as existing and filled with default values:
    | {"user":{"access_token":"","account_id":"test_001","platform":"Facebook"}

    I don't want these data to go to server.Are there alternative json parsers?
    PS:I always considered json as something trivial.Surprisingly unity doesn't have such core functionality.
     
  2. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    It does, you just have to know how the tools work.

    Unity's serialization engine treats public fields as serializable, so that's what happens there. There are attributes to explicitly mark them serializable and non-serializable etc.

    Try the
    System.NonSerializedAttribute
    or encapsulate the fields properly, so that the default for private/protected fields applies (not serialized).
     
    eses likes this.
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,378
    The functionality is there.

    Your example demonstrates that it is there.

    What your example also demonstrates is that it doesn't do it in the manner you like. Disliking something does not mean it doesn't exist.

    The issue it sounds your having is that the serializer inserts objects into fields that are null. And yes, that's how the Unity serializer works.

    JsonUtility.ToJson follows the same rules that the built in yaml serializer Unity uses for your prefabs/scenes. Those too also fill in null fields with objects.

    I too don't like this.

    But it's how it works.

    If you'd like something else there are plenty of 3rd party json serializers out there lilke Json.Net. I also know that someone in the forums here has a pretty decent serializer as well (they might come along and plug it). Or you can write a custom formatter to work with the built-in .Net serializer... so instead of a BinaryFormatter, you have a JsonFormatter, like this one I wrote here:
    https://github.com/lordofduct/space...ree/master/SPSerialization/Serialization/Json
     
  4. undefined666

    undefined666

    Joined:
    Apr 3, 2018
    Posts:
    53
    But what if its subclass of BaseRequest who decide whether fill user data or leave it null(in the latter case request will be treated as request from unathorized user)I'd like to handle both requests with the same logic

    When I said 'core functionality' I meant regular json parsers like in javascript or java who add no extra data for null objects.For intense client-server interaction this may generate lot of unnecessary traffic.Is there way to avoid it in unity?

    Thanks! I'll have a look on it.
     
    Last edited: Sep 23, 2018
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,378
    While I agree it's annoying, it's still has the core funcationlity. It serailizes, and creates json. That would be core functionality. Its rules for doing so have to do with each system and each system may have their own rules. You have an expectation for rules similar to those of the libraries found typically in Javascript and Java. Unity doesn't use those same libraries.

    Unity on the other hand already had an existing serializer, it just had to add json formatting to the serializer.

    Anyways, if they changed the rules, that would mean their json serializer followed different rules from their other serializers. We now have 2 serializers to maintain, AND users would be left having to learn the rule set of yet another serializer made by Unity.

    Especially since legacy wise this is a fairly new thing added to Unity. There have been years and years of no built-in json support which has always been suplemented by 3rd party libraries. This even goes for .Net/mono in and of itself, they have always pointed you in the direction of something like Json.Net.

    I mean sure, Javascript has built-in support. It's Javascript... JSON, or javascript object notation, is born in javascript.

    Java on the other hand is different. For starters there are tons of libraries to Java for Json support. Just like for .Net. Though the Java team did add direct support for it in I believe Java 7, but people still often prefer the alternative libraries for speed purposes. The reason Java added it is something I can only guess at since I'm not the board of members who decide those things... but Java is often used in enterprise settings for web communication, so adding json support made sense, and it made sense to follow the existing javascript rules for it.

    Unlike Unity. Unity is not enterprisey, Unity is not for web communication. Unity is a game engine. Serialization in game engines isn't usually for web/net talk (there's Unet for that... which communicates binary not json because json is fat regardless of the null behaviour). Serialization is often used for saving data to disk ala save files. This is what the community was clammering for... not so they could send web messages, but so they can have an easy way to save their game state to disk for later loading. So Unity obliged in like Unity 5 (if I remember correctly), and since it was for saving to disk they followed the same rule set established years prior for their existing serializing to disk serializer.

    You should not assume a product comes with json support built in. That's how programming works. You usually import packages/libraries to handle auxiliary tasks. Like python doesn't directly have json support in the language, instead you use 'json' library. Or in C/C++ has a bajillion different libraries for json (in usual C fashion). Why bloat up a code base with core libraries if you only need them for specific kinds of projects. Instead you include them as you need them.

    This bloating is something that bit Microsoft in the ass. Back in the early 2000's when they released C# for the first time they included core XML functionality into .Net. It's now a haggered old pile of code that is force included in all .net packages and has like 3 different functionality/versions in itself. It's a giant pile of baggage that follows it around. So when Json became popular 10 years later... Microsoft had the chance to add it and decided against it because well... libraries exist, why bloat up the code base when you can quickly and easily just click your package manager and add Json.Net.

    Same goes for Unity. Unity has lots of baggage after a decade of existing. Why should they add yet another serialization library to their code base when they could just re-use the existing one (the yaml/binary serializer they already use)? Users were already clammering for Unity to shrink their filesize (primarily for mobile builds). What motivation did they have for adding yet another hunk of code to support in their code base?
     
  6. undefined666

    undefined666

    Joined:
    Apr 3, 2018
    Posts:
    53
    Ok, so its due to historical reasons.
    But Unity do have json support.Which I believe should be default choice in most cases.I'm former flash developer my work now is to port old project from flash to unity.We can't just rewrite backend so it communicate with binary data as it will break old clients.I'd better try one of the 3rd party parsers mentioned here.
     
  7. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,378
    Yes, it has support. A late added formatter ontop of an existing serializer that was not designed with web messages in mind.

    I full heartedly suggest you use Json.Net

    It is the most popular .Net library for web messages formatted in json and generally uses the same rules you would find in javascript and java.

    https://assetstore.unity.com/packages/tools/input-management/json-net-for-unity-11347
    This asset store version takes the existing Json.Net library and massages it a bit so that it works when targeting iOS and other il2cpp targets.
     
  8. undefined666

    undefined666

    Joined:
    Apr 3, 2018
    Posts:
    53
    Json.NET is super!
    Here is the code for serializing object with respect of null values
    Code (CSharp):
    1. string jsonStr = JsonConvert.SerializeObject(data, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });