Разбор JSON с 2D-массивами в Unity C # - PullRequest
0 голосов
/ 18 марта 2019

Я работаю с Unity и Python и отправляю данные по UDP моему клиенту Unity. Я отправляю JSON, который успешно достигает моего приложения Unity. Я не могу понять, как правильно разобрать этот JSON. Я пробовал:

JsonUtility.FromJson<T>(...)

но результат был неверным. Я реализовал класс [System.Serializable], который содержал типы данных

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

И инициализировал их в моем конструкторе, используя

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

Каждый раз, когда я пытаюсь распечатать результат, все мои переменные пусты.

Мой JSON выглядит так -

{
    "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..]
     ]
}

Любая помощь приветствуется.

1 Ответ

1 голос
/ 19 марта 2019

Ваш JSON все еще странно отформатирован, и я не понимаю вашу структуру данных.

Почему вы храните все в List<int[]>, тогда как полученные значения явно float (или double)ценности?

Если что-то должно быть

[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[]>();
}

Посмотрите на этот JSON в c # конвертер !

НО в любом случае 1017 * Unity, похоже, не поддерживает десериализацию вложенных массивов и списков!Я предполагаю, что причина в том, что, хотя у других примитивных типов данных значение по умолчанию отличается от нуля, List и массивы null являются значениями по умолчанию и должны быть инициализированы перед их заполнением.JsonUtility, кажется, не поддерживает это.Я думаю, что это связано с

Обратите внимание, что, хотя в этот метод можно передавать примитивные типы, результаты могут отличаться от ожидаемых;вместо того, чтобы сериализовать их напрямую, метод попытается сериализовать их общедоступные поля экземпляра, в результате получая пустой объект. Аналогично, передача массива этому методу приведет не к созданию массива JSON, содержащего каждый элемент, а к объекту, содержащему открытые поля самого объекта массива (которых нет ни одного).Чтобы сериализовать фактическое содержимое массива или примитивного типа, необходимо заключить его в класс или структуру. ( JsonUtility.ToJson )

и

поле типа T будет иметь значение по умолчанию (T) - ему не будет присвоено значение, указанное в качестве инициализатора поля, , поскольку конструктор для объекта не выполняется во время десериализации ( JsonUtility.FromJson )


Однако зачем даже принимать их за массивы, где каждый из ваших массивов имеет только один элемент в любом случае, когда кажется(и ваши имена и название говорят) вы предпочитаете хранить кортежи всегда 2 и 3 чисел?

В случае, если вы можете изменить формат JSON, вам, скорее всего, захочется что-то вроде

[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>();
}

И ваш JSON должен выглядеть скорее как

{
    "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}, 
        ...
     ]
}

Самый простой способ увидеть, как на самом деле должен выглядеть ваш JSON, - это взять ваш класс JsonData и сериализовать его один раз, чтобы вы увидели, что такое Unity.ожидает как 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);

Если изменение формата JSON не является вариантом, вместо этого вы можете взглянуть на SimpleJSON , который не десериализуется непосредственно в экземпляр класса, а скорееJSONNode, который может содержать вложенные списки и массивы, например

var jsonData = JSON.Parse(yourJson);
var firstEuerAngles = jsonData["eulerAngles"][0];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...