Parsing Nested Arrays with JsonUtility

I’m trying to parse this Json file with JsonUtility, the only problem is I cannot get the array of coordinates.

{
"features": [
{ "type": "Feature", "properties": { "id": 1.000000, "osm_id": -60.255, "name": "test", "type": "test" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 11.363926, 3.544844 ], [ 11.363489, 3.398182 ] ] ] } } ]
}

This is my code:

[System.Serializable]
public class features{
    public string type;
	public properties properties;
    public geometry geometry;
};
    
[System.Serializable]
public class PlayerStatsList {
    public List <features> features;
};

[System.Serializable]
public class properties{    
	public int id;
	public int osm_id;
	public string name;
	public string type;
    }

[System.Serializable]
public class geometry{
    public string type;
    //some way to get coordinates
}

I have tried some ways of accessing coordinates from other solutions like class of float array in a nested class, but it doesn’t work, any help would be appreciated.

That’s not possible with Unity’s JsonUtility. You have to understand that the JsonUtility is not a general purpose JSON serializer / parser. It is build on top of Unity’s serialization logic. Nested / jagged arrays or multidimensional arrays aren’t supported by Unity’s serialization system, so they can’t be deserialized.

You basically have two options:

  • either build your serializable classes in a way that Unity can serialize and derive your JSON structure from that.
  • or if you want to use your own JSON structure, don’t use JsonUtility and use a general purpose JSON parser.

One example would be my [SimpleJSON][1] parser. It’s far from being perfect and doesn’t deserialize to actual classes, but allow easy access to any information stored in a JSON file.

You can also easily add extension method to simplify the usage of certain Unity types. For example:

public static class JSONNodeUnityExt
{
    public static Vector4 ToVector4(this JSONNode aNode)
    {
        if (aNode is JSONArray)
            return new Vector4(aNode[0].AsFloat, aNode[1].AsFloat, aNode[2].AsFloat, aNode[3].AsFloat);
        else if (aNode is JSONClass)
            return new Vector4(aNode["x"].AsFloat, aNode["y"].AsFloat, aNode["z"].AsFloat, aNode["w"].AsFloat);
        return Vector4.zero;
    }
    public static Vector3 ToVector3(this JSONNode aNode)
    {
        if (aNode is JSONArray)
            return new Vector3(aNode[0].AsFloat, aNode[1].AsFloat, aNode[2].AsFloat);
        else if (aNode is JSONClass)
            return new Vector3(aNode["x"].AsFloat, aNode["y"].AsFloat, aNode["z"].AsFloat);
        return Vector3.zero;
    }
    public static Vector2 ToVector2(this JSONNode aNode)
    {
        if (aNode is JSONArray)
            return new Vector2(aNode[0].AsFloat, aNode[1].AsFloat);
        else if (aNode is JSONClass)
            return new Vector2(aNode["x"].AsFloat, aNode["y"].AsFloat);
        return Vector2.zero;
    }
}

This allows easy conversion of a JSONNode into a Vector2/3/4. In your specific case you could do:

var v1 = rootNode["features"][0]["geometry"]["coordinates"][0][0].ToVector2();
var v2 = rootNode["features"][0]["geometry"]["coordinates"][0][1].ToVector2();

Of course you usually don’t use the full path every time:

var coords =  rootNode["features"][0]["geometry"]["coordinates"][0];
for(int i = 0; i < coords.Count; i++)
{
    var v = coords*.ToVector2();*


}
Of course you can also make an extension method that converts a JSONNode into a list of coordinates:
public static List ToVector2List(this JSONNode aNode)
{
if (aNode == null || !(aNode is JSONArray))
return null; // or new List();
var list = new List(aNode.Count);
for(int i = 0; i < aNode.Count; i++)
{
var v = aNode*.ToVector2();*
list.Add(v);
}
return list;
}
Now you could simply do:
List coords = rootNode[“features”][0][“geometry”][“coordinates”][0].ToVector2List();
If you prefer arrays, just create an extension for that ^^.
Of course there are other JSON parsing solutions out there. [LitJson][2] is quite popular but has it’s own restrictions.
_[1]: http://wiki.unity3d.com/index.php/SimpleJSON*_
_
[2]: https://lbv.github.io/litjson/docs/quickstart.html*_

something like:

public Vector2[] coordinates;