Unity Десериализация вложенного JSON

Я пытаюсь создать систему рекордов, используя firebase для проекта Unity. Чтобы получить JSON, я использую RESTCLIENT. Мне удалось нормально загрузить оценки, но их десериализация оказалась проблемой.

JSON = "{"UserName1":{"Name":"UN1","ScoreVal":"99/100"},"UserName2":{"Name":"UN2","ScoreVal":"100/100"}}"

[Serializable]
public class RootObject
{
    public Score score { get; set; }
}

[Serializable]
public class Score
{
    public string Name;
    public string ScoreVal;

    public Score(string name, string scoreVal)
    {
        this.Name = name;
        this.ScoreVal = scoreVal;
    }
}

Идеальное решение будет следовать этому формату JSON:

{
    "Level1":{
        "User1":{
            "Name":"User1",
            "Score":"100/100"
            },
        "User2":{
            "Name":"User2",
            "Score":"100/100"
            }
        },
    "Level2": {
        "User1": {
            "Name":"User1",
            "ScoreVal":"99/100"
        },
        "User2": {
            "Name":"User2",
            "ScoreVal":"100/100"
        }
    }
}

Я пробовал использовать JsonUtility из единства, newtonsoft и моего собственного jsonhelper:

public static class JsonHelper2
{
public static T[] FromJson<T>(string json)
{
    Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(json);
    return wrapper.Items;
}

public static string ToJson<T>(T[] array)
{
    Wrapper<T> wrapper = new Wrapper<T>();
    wrapper.Items = array;
    return JsonUtility.ToJson(wrapper);
}

public static string ToJson<T>(T[] array, bool prettyPrint)
{
    Wrapper<T> wrapper = new Wrapper<T>();
    wrapper.Items = array;
    return JsonUtility.ToJson(wrapper, prettyPrint);
}

[Serializable]
private class Wrapper<T>
{
    public T[] Items;
}

}

Я могу получить данные, когда есть только одна запись, но я не могу получить баллы, когда есть несколько имен пользователей.


person Zerux    schedule 11.04.2019    source источник


Ответы (1)


Ваш json имеет фиксированное количество уровней и фиксированное количество пользователей. На самом деле вам понадобится такой объект, чтобы десериализовать его:

public class Scores
{
    public Users Level1 {get;set;}
    public Users Level2 {get;set;}
}

public class Users
{
    public User User1 {get;set;}
    public User User2 {get;set;}
}

public class User
{
    public string Name {get;set;}
    public string Score {get;set;}
}

Предполагая, что ваше намерение состояло не только в том, чтобы иметь 2 фиксированных уровня и 2 фиксированных пользователя, ваш json должен быть структурирован следующим образом (обратите внимание, что уровни представляют собой массив, а оценки внутри уровня - это массивы):

{
    "levels": [{
            "name": "Level 1",
            "scores": [{
                "user": "User1",
                "score": "8/10"
            }, {
                "user": "User2",
                "score": "7/10"
            }]
        },
        {
            "name": "Level 2",
            "scores": [{
                "user": "User1",
                "score": "9/10"
            }, {
                "user": "User3",
                "score": "6/10"
            }]
        }
    ]
}

Тогда ваши классы C # будут:

public class Score
{
    public string user {get;set;}
    public string score {get;set;}
}

public class Level
{
    public string name {get;set;}
    public IList<Score> scores {get;}

    public Level()
    {
        scores = new List<Score>();
    }
}

public class RootObject
{
    public IList<Level> levels {get;}

    public RootObject()
    {
        levels = new List<Level>();
    }
}

Если на самом деле вы действительно пытаетесь отслеживать только 2 фиксированных уровня с оценками для 2 фиксированных пользователей, ваш json должен работать с исходной структурой классов, которую я представил.

person Colin Young    schedule 11.04.2019
comment
Привет, Колин, спасибо за ответ. Проблема, с которой я сталкиваюсь, заключается в том, что у меня нет фиксированного количества пользователей. Уровни зафиксированы на 10, так что это не такая уж большая проблема, поскольку я МОГ сделать то, что вы описали выше. Есть идеи, как я могу заставить его работать для неопределенного количества пользователей? - person Zerux; 11.04.2019
comment
Структура json, которую я вложил в свой ответ, допускает неограниченное количество уровней и неограниченное количество высоких баллов за уровень. Обратите внимание на массивы level объектов, которые сами содержат массивы HighScore объектов. Насколько вы в целом знакомы с json? - person Colin Young; 11.04.2019
comment
Вам может оказаться полезным json2csharp.com. Он сгенерирует для вас класс C # из образца json. - person Colin Young; 11.04.2019
comment
Ах да, я просто сумел это реализовать. Спасибо! Я впервые использую json. - person Zerux; 11.04.2019
comment
@ColinYoung спасибо за совет json2csharp - хорошая экономия времени - person zambari; 12.04.2019