Unity Serializing Nested Dictionary to JSON

10,282

JsonUtility is the fastest way to use jsons as it doesn't generate almost any GC. The problem is that it isn't very flexible because you need to know in advance the data structure and it cannot be mutated as it needs a class.

If you need to use Jsons as dictionaries you can use either MiniJSON (just right clic and Save As...) or JSONObject, both are free and work in every platform altough they are a lot slower than JsonUtilty, so if you are parsing big jsons or need to do it a lot of times while the performance matters then it isn't going to be fluid.

I personally have used both and they are great, MiniJSON is a bit easier to use while JSONObject is a little bit more potent but also a little bit more difficult to start with.

EDIT:

As mentioned in one of the comments you can also use Newtonsoft, I think it is faster than minijson and jsonobject but might be overkill if you aren't doing a lot of stuff with jsons.

Share:
10,282
hotshotiguana
Author by

hotshotiguana

Updated on June 19, 2022

Comments

  • hotshotiguana
    hotshotiguana almost 2 years

    The REST service I am using, RSA Archer, is expecting an integer key which means I simply can't nest [Serializable] objects and then JsonUtility.ToJson() to create the serialized JSON string. I thought I found a solution to create a Dictionary object and then use ISerializationCallbackReceiver to handle just the dictionary piece of the nested structure, but the code below simply ignores that part of the nested object and doesn't serialize the Dictionary. Does anyone have any thoughts on the best approach to this?

    Expected Output:

    {"Content": {"LevelId": 10,"FieldContents": {"47": {"Type": 1, "Value": "me", "FieldId": 47}}}}
    

    Object Structure:

    [Serializable]
    public class Record
    {
        public Content Content;
    }
    
    [Serializable]
    public class Content
    {
        public int LevelId;
        public FieldContents FieldContents;
    }
    
    public class FieldContents : ISerializationCallbackReceiver
    {
        public Dictionary<string, FieldValue> FieldValues;
    
        public List<string> dicKeys;
        public List<FieldValue> dicVals;
    
        public void OnBeforeSerialize ()
        {
            dicKeys.Clear ();
            dicVals.Clear ();
            foreach (var kvp in FieldValues) {
                dicKeys.Add (kvp.Key);
                dicVals.Add (kvp.Value);
            }
        }
    
        public void OnAfterDeserialize ()
        {
            FieldValues = new Dictionary<string, FieldValue> ();
            for (int i = 0; i < Math.Min (dicKeys.Count, dicVals.Count); i++) {
                FieldValues.Add (dicKeys [i], dicVals [i]);
            }
        }
    }
    
    [Serializable]
    public class FieldValue
    {
        public int Type;
        public string Value;
        public int FieldId;
    }
    

    JSONUtility and Instantiation:

    Record newRecord = new Record () { Content = new Content () {
                    LevelId = 10,
                    FieldContents = new FieldContents () { FieldValues = new Dictionary<string, FieldValue> () { {
                                "47",
                                new FieldValue () {
                                    Type = 1,
                                    Value = "me",
                                    FieldId = 47
                                }
                            }
                        }
                    }
                }
            };
    Debug.Log (JsonUtility.ToJson (newRecord));
    
  • hotshotiguana
    hotshotiguana about 7 years
    Thanks @Juan. I am certainly not opposed to 3rd party libraries, but when I used LitJSON to do this I ran into many issues getting it to work with the Hololens, hence the fallback to JsonUtility. I will test out those other libraries and see how they do.
  • Juan Bayona Beriso
    Juan Bayona Beriso about 7 years
    I recommend you minijson if you don't need to parse big jsons, it's only a script and it is super easy to use. Google and Facebook are using it in their sdks for unity