Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity Serializing Nested Dictionary to JSON

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));
like image 697
hotshotiguana Avatar asked Feb 08 '17 02:02

hotshotiguana


Video Answer


1 Answers

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.

like image 182
Juan Bayona Beriso Avatar answered Oct 18 '22 18:10

Juan Bayona Beriso