2

I am working with Unity and Python and sending data over UDP to my Unity client. I am sending a JSON which reaches my Unity application successfully. I can't figure out how to properly parse this JSON. I have tried :

JsonUtility.FromJson<T>(...)

but the result wasn't correct. I implemented a [System.Serializable] class which contained data types

List<List<int>> landmarks;
List<double> eulerAngles;
List<List<double>> boxPoints;

And initialized these in my constructor using

landmarks = new List<List<int>>(); 
...

Every time I try to print the result, all my variables are empty.

My JSON looks like this -

{
    "eulerAngles": [6.2255, -15.8976, -0.5881], 
    "boxPoints": [
        [194.05965, 194.15782], 
        [182.35829, 189.05042], 
        [6 more...]
    ], 
    "landmarks": [
        [196, 225], 
        [197, 242], 
        [199, 258], 
        [65 more..]
     ]
}

Any help appreciated.

4
  • I have tried .. and what was the result? Any errors? What exactly didn't work as expected? ... are all your values supposed to be arrays? your JSON should rather look like e.g. 'eulerAngles': ["x":6.2255, "y":-15.8976, "z":-0.5881], and your boxPoints like [{"x":194.05965, "y":194.15782}, {182.35829, 189.05042}, ... ], etc (see JSON Format) Commented Mar 18, 2019 at 20:16
  • @dbc I have edited my question and added more details. I have tried jsonlint.com and it shows I have a valid JSON. Any help appreciated! Thanks! Commented Mar 18, 2019 at 21:25
  • @derHugo I have edited my question to make it more clear. Any help appreciated. Commented Mar 18, 2019 at 21:26
  • Hi @NalinKamboj - [[6.2255], [-15.8976], [-0.5881]] these are floats, not ints. The parser will not be able to serialize those as integers. Commented Mar 19, 2019 at 0:30

1 Answer 1

3

Your JSON is still strangly formatted and I don't understand your data structure.

Why are you storing everything in List<int[]> while the values you get are clearly float (or double) values?

If something it should probably be

[Serializable]
public class JsonData
{
    // here maybe int is ok at least from your data it seems so
    public List<int[]> landmarks = new List<int[]>();

    // for those you clearly want floats
    public List<float[]> eulerAngles = new List<float[]>();
    public List<float[]> boxPoints = new List<float[]>();
}

Have a look at this JSON to c# converter!

BUT anyway Unity's JsonUtility seems not to support the deserialization of nested arrays and lists! I guess the reason is that while other primitive data types have a default value that is different from null, List and arrays are null be default and have to be initialized before filling them. JsonUtility seems to not support that. I think it is related to

Note that while it is possible to pass primitive types to this method, the results may not be what you expect; instead of serializing them directly, the method will attempt to serialize their public instance fields, producing an empty object as a result. Similarly, passing an array to this method will not produce a JSON array containing each element, but an object containing the public fields of the array object itself (of which there are none). To serialize the actual content of an array or primitive type, it is necessary to wrap it in a class or struct. (JsonUtility.ToJson)

and

a field of type T will have value default(T) - it will not be given any value specified as a field initializer, as the constructor for the object is not executed during deserialization (JsonUtility.FromJson)


However, why even take them as arrays where every of your arrays only has one element anyway when it seems (and your names and title say) you rather want to store tuples of allways 2 and 3 numbers?

In case you can change the JSON format it seems like you rather would want something like

[Serializable]
public class JsonData
{
    // here maybe int is ok at least from your data it seems so
    public List<Vector2Int> landmarks = new List<Vector2Int>();

    // for those you clearly want floats
    public List<Vector3> eulerAngles = new List<Vector3>();
    public List<Vector2> boxPoints = new List<Vector2>();
}

And your JSON should than rather look like

{
    "eulerAngles": [
        {"x":6.2255, "y":-15.8976, "z":-0.5881},
        ...
    ], 
    "boxPoints": [
        {"x":194.05965, "y":194.15782}, 
        {"x":182.35829, "y":189.05042}, 
        ...
    ], 
    "landmarks": [
        {"x":196, "y":225}, 
        {"x":197, "y":242}, 
        {"x":199, "y":258}, 
        ...
     ]
}

The simplest way to see how your JSON should actually look like would be to take your JsonData class and serialize it once so you see what Unity expects as JSON.

var testData = new JsonData();
// fill it with example values
testData.eulerAngles = new List<Vector3>()
{
    new Vector3(6.2255f, -15.8976f, -0.5881f)
};
testData.boxPoints = new List<Vector2>()
{
    new Vector2(194.05965f, 194.15782f), 
    new Vector2(182.35829f, 189.05042f)
};
testData.landmarks = new List<Vector2Int>()
{
    new Vector2Int(196, 225),
    new Vector2Int(197, 242),
    new Vector2Int(199, 258)
}

var result = JsonUtility.ToJson(testData);

If changing the JSON format is not an option you could instead have a look at SimpleJSON which doesn't deserialize directly into a class instance but rather to a JSONNode which can contain nested lists and arrays e.g.

var jsonData = JSON.Parse(yourJson);
var firstEuerAngles = jsonData["eulerAngles"][0];
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your response. Changing my class like you suggested and my JSON worked perfectly. Thank you!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.