Сбой десериализации объекта в формате Json

#c# #.net #json #json.net

#c# #.net #json #json.net

Вопрос:

Я пытаюсь десериализовать этот файл JSON в объект, но не могу заставить его работать.

Json:

 "hotkeySets": {
     "Player 1": {
          "chatOff": [
                    {
                    "actionsetting": {
                            "action": "Togglelist"
                        },
                        "keysequence": "Ctrl B"
                    },
                    {
                        "actionsetting": {
                            "action": "Copy"
                        },
                        "keysequence": "Ctrl C"
                    },
                    {
                        "actionsetting": {
                            "useObject": 3308,
                            "useType": "SelectUseTarget"
                        },
                        "keysequence": "F10"
                    },
                ],
                "chatOn": [
                    {
                        "actionsetting": {
                            "action": "Select All"
                        },
                        "keysequence": "Ctrl A"
                    },
                    {
                        "actionsetting": {
                            "chatText": "heal friend",
                            "sendAutomatically": true
                        },
                        "keysequence": "Ctrl F1"
                    },
                    {
                        "actionsetting": {
                            "action": "Copy"
                        },
                        "keysequence": "Ctrl C"
                    },
                ]
            },
            "Player 2": {
                "chatOff": [
                    {
                        "actionsetting": {
                            "action": "ToggleBattlelist"
                        },
                        "keysequence": "Ctrl B"
                    },
                    {
                        "actionsetting": {
                            "action": "Copy"
                        },
                        "keysequence": "Ctrl C"
                    },
            }
}
  

И вот код, который я использую для его десериализации:

 JToken hotkeyConfig = JObject.Parse(json)
JToken hotkeysSet = hotkeyConfig.SelectToken("hotkeySets");

var sets = JsonConvert.DeserializeObject<Dictionary<string, JObject>>(hotkeysSet.ToString());

foreach (var hotkeySet in sets) {
    string hotkeySetName = hotkeySet.Key; // "Player 1" etc..
    List<Hotkey> hotkeys = new List<Hotkey>();

    foreach (var hotkey in hotkeySet.Value) {

        Hotkey htk = JsonConvert.DeserializeObject<Hotkey>(hotkey.Value.ToString());    
     }
 }
  

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

 public class Hotkey {

        [JsonProperty("actionsetting")]
        public ActionSetting actionsetting;

        [JsonProperty("keysequence")]
        public string Shortcut { get; set; }

        public class ActionSetting {
            public int useObject{ get; set; }

            public string chatText { get; set; }

            public string useType{ get; set; }

            public bool sendAutomatically{ get; set; }
        }
    }
  

Сбой происходит в строке «JsonConvert.DeserializeObject», указывающий недопустимый формат, поэтому, вероятно, я что-то упускаю в своей структуре классов, я думаю.

Комментарии:

1. Ваш код не компилируется. Что такое hotkeyConfig? Просто прочитав ваш код, что-то не так? Почему вы вызываете deserialize object так много раз, когда у вас есть только один файл JSON? Один вызов для десериализации должен быть в состоянии получить вам весь объектный граф.

2. Это просто Json. Parse(), он вызывается «несколько» раз, потому что ключи «Player 1», «Player 2» и т. Д. Все Они Динамические, Поэтому не обязательно они получат эти имена, это может быть любое имя, и десериализация словаря была способом, который я нашел, чтобы получить это имя(работает), но когда я пытаюсь десериализовать значение, оно падает

3. Можете ли вы просто предоставить нам репозиторий, который можно скомпилировать и запустить?

4. Кажется, вам не хватает action свойства в ActionSetting классе.

Ответ №1:

Прежде всего, в вашем файле Json ошибка. Вы не закрываете массив «chatOff» для «Player 2». Проверьте это ниже, где я закрыл его на строке перед последней:

 "Player 2": {
    "chatOff": [
        {
            "actionsetting": {
                "action": "ToggleBattlelist"
            },
            "keysequence": "Ctrl B"
        },
        {
            "actionsetting": {
                "action": "Copy"
            },
            "keysequence": "Ctrl C"
        },
    ]
}
  

Во-вторых, ваш подход к отображению в горячую клавишу хорош, но вы не можете отобразить элементы вашего массива непосредственно в класс горячих клавиш. В качестве альтернативы вы можете сопоставить новый объект для представления вашего проигрывателя, а затем сопоставить свойства «chatOff» и «ChatON» в списках. Сделайте ваши классы Json похожими на это:

 public class Player
{
    [JsonProperty("chatOff")]
    public List<Hotkey> ChatOff { get; set; }

    [JsonProperty("chatOn")]
    public List<Hotkey> ChatOn { get; set; }
}

public class Hotkey
{
    [JsonProperty("actionsetting")]
    public ActionSetting ActionSetting;

    [JsonProperty("keysequence")]
    public string Shortcut { get; set; }
}

public class ActionSetting
{
    [JsonProperty("useObject")]
    public int UseObject { get; set; }

    [JsonProperty("chatText")]
    public string ChatText { get; set; }

    [JsonProperty("useType")]
    public string UseType { get; set; }

    [JsonProperty("sendAutomatically")]
    public bool SendAutomatically { get; set; }
}
  

Наконец, сделайте ваш десериализующий код похожим на это:

 var hotkeyConfig = JObject.Parse(json);

var playersToken = hotkeyConfig.SelectToken("hotkeySets");

var playersDictionary = 
    JsonConvert.DeserializeObject<Dictionary<string, JObject>>(
        playersToken.ToString());

foreach (var playerEntry in playersDictionary)
{
    var player = JsonConvert.DeserializeObject<Player>(playerEntry.Value.ToString());
}
  

Комментарии:

1. Просто к вашему сведению, но вам не нужны все эти JsonProperty атрибуты. JSON.NET сопоставит имена camelCase в JSON с именами PascalCase в . ЧИСТЫЙ класс, если имена совпадают без учета регистра. Единственный раз, когда вам нужно JsonProperty , это если имена не совпадают. В противном случае они просто создают «шум».

2. Конечно, @CraigW. Я делаю это в основном для упрощения на случай, если Cartel захочет изменить имена свойств.

Ответ №2:

Проверьте свою строку Json, формат плохой, как показывает ошибка. Здесь я предоставляю вам правильный формат для строки Json, которую вы опубликовали.

 {
"hotkeySets": {
    "Player 1": {
        "chatOff": [{
            "actionsetting": {
                "action": "Togglelist"
            },
            "keysequence": "Ctrl B"
        }, {
            "actionsetting": {
                "action": "Copy"
            },
            "keysequence": "Ctrl C"
        }, {
            "actionsetting": {
                "useObject": 3308,
                "useType": "SelectUseTarget"
            },
            "keysequence": "F10"
        }],
        "chatOn": [{
            "actionsetting": {
                "action": "Select All"
            },
            "keysequence": "Ctrl A"
        }, {
            "actionsetting": {
                "chatText": "heal friend",
                "sendAutomatically": true
            },
            "keysequence": "Ctrl F1"
        }, {
            "actionsetting": {
                "action": "Copy"
            },
            "keysequence": "Ctrl C"
        }]
    },
    "Player 2": {
        "chatOff": [{
            "actionsetting": {
                "action": "ToggleBattlelist"
            },
            "keysequence": "Ctrl B"
        }, {
            "actionsetting": {
                "action": "Copy"
            },
            "keysequence": "Ctrl C"
        }]
    }
}
}
  

вот средство проверки Json, в котором вы можете его протестировать JsonValidator
Я надеюсь, что это решит вашу проблему.