#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
Я надеюсь, что это решит вашу проблему.