Json.NET десериализует список выбора/список выбора

Я сериализовал MultiSelectList с Json.NET в ASP.NET (с включенной обработкой TypeNameHandling), что дало следующий результат:

"MyMultiSelectList": {
    "$type": "System.Web.Mvc.MultiSelectList, System.Web.Mvc",
    "$values": [
      {
        "Disabled": false,
        "Selected": true,
        "Text": "Text1",
        "Value": "Value1"
      },
      {
        "Disabled": false,
        "Selected": false,
        "Text": "Text2",
        "Value": "Value2"
      },
      {
        "Disabled": false,
        "Selected": false,
        "Text": "Text3",
        "Value": "Value3"
      }
    ]
  }

При десериализации этого Json обратно в MultiSelectList без каких-либо пользовательских преобразователей с использованием этого метода, я получаю MultiSelectList с 3 SelectListItems, где для их свойства Text установлено значение «System.Web.Mvc.SelectListItem», а их свойство Value пусто.

Во-первых, я предположил, что Json.NET не может правильно десериализовать SelectListItems, поэтому я сделал Пользовательский JsonConverter для типа SelectListItem. Мой преобразователь правильно создал SelectListItems, но результат остался прежним.

Затем я попытался создать собственный преобразователь для типа MultiSelectList, но этот код никогда не вызывается Json.NET.

Возможно, эта проблема как-то связана с тем фактом, что MultiSelectList не имеет пустого конструктора по умолчанию, но у меня нет возможности попробовать.


person Stijn    schedule 19.11.2018    source источник


Ответы (1)


Создайте пользовательский класс с QuickType:

public class CustomSelectList
    {
        [JsonProperty("MyMultiSelectList")]
        public MyMultiSelectList MyMultiSelectList { get; set; }
    }

    public class MyMultiSelectList
    {
        [JsonProperty("$type")]
        public string Type { get; set; }

        [JsonProperty("$values")]
        public Value[] Values { get; set; }
    }

    public class Value
    {
        [JsonProperty("Disabled")]
        public bool Disabled { get; set; }

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

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

        [JsonProperty("Value")]
        public string ValueValue { get; set; }
    }

десериализовать это

var customList = JsonConvert.DeserializeObject<CustomSelectList>(json);

а затем загрузить его в список

foreach (var item in customList.MyMultiSelectList.Values)
    multiSelectList.Add(new SelectListItem{ Value= item.ValueValue, Text=item.Text });

и заполните MultiSelectList (еще не проверено)

var multiList = new MultiSelectList(list);

Другой подход заключается в том, чтобы сначала загрузить его в структуру данных, которая поддерживает сериализацию (например, List<KeyValuePair<string,string>>:

var serializableList = new List<KeyValuePair<string, string>>();
foreach(var item in selectList)
    serializableList.Add(new KeyValuePair<string, string>(item.Text, item.Value));

А затем сериализуйте serializableList, вы получите

[{"Key":"select item value","Value":"select item text"}]

Если вы хотите сохранить больше информации, например, выбран ли элемент, вы можете сделать List<Tuple<string,string,bool>>

когда вам нужно перестроить свой MultiSelectList, просто десериализуйте его, добавьте в List<SelectListItem>, а затем передайте список для создания MultiSelectList (new MultiSelectLust(list))

person Hanjun Chen    schedule 19.11.2018
comment
Звучит как довольно хорошая идея, однако я не могу вызвать sonConvert.DeserializeObject<CustomSelectList>(json) напрямую, так как мой MultiSelectList содержится в каком-то другом объекте на 3-х уровнях. - person Stijn; 20.11.2018
comment
В этом случае вы можете сделать dynamic list = JObject.Parse(json); и получить к нему доступ с корневого уровня. - person Hanjun Chen; 21.11.2018
comment
Это тоже проблема, я думаю. Я не знаю, есть ли там MultiSelectList или нет. Иногда он есть, но иногда нет. - person Stijn; 22.11.2018
comment
Чего вы хотите добиться от сериализации списка множественного выбора? Вы можете хранить значения в сериализуемом/десериализуемом списке‹T›, а затем делать с ним все, что хотите. - person Hanjun Chen; 22.11.2018
comment
Я обнаружил, в чем именно заключалась моя проблема: поскольку я десериализую в Dictionairy‹string, object› (и SelectList является одним из объектов), Json.NET не запускает пользовательский преобразователь для SelectList (поскольку тип будет объектом вместо SelectList). Однако наличие пользовательского преобразователя для Dictionairy‹string, object› позволяет мне использовать представленный вами класс для сериализации и десериализации, выполняя сериализацию словаря Json.NET по умолчанию и вмешиваясь, когда я создаю (Multi)SelectList. - person Stijn; 28.11.2018