2017-01-06 2 views
6

Я очень новичок в JSON, пожалуйста, помогите!Сериализованный список <KeyValuePair <строка, строка >> как JSON

Я пытаюсь сериализация List<KeyValuePair<string, string>>, как JSON

Сейчас:

[{"Key":"MyKey 1","Value":"MyValue 1"},{"Key":"MyKey 2","Value":"MyValue 2"}] 

Ожидаемое:

[{"MyKey 1":"MyValue 1"},{"MyKey 2":"MyValue 2"}] 

я упомянул несколько примеров из this и this.

Это мой KeyValuePairJsonConverter: JsonConverter

public class KeyValuePairJsonConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     List<KeyValuePair<object, object>> list = value as List<KeyValuePair<object, object>>; 
     writer.WriteStartArray(); 
     foreach (var item in list) 
     { 
      writer.WriteStartObject(); 
      writer.WritePropertyName(item.Key.ToString()); 
      writer.WriteValue(item.Value.ToString()); 
      writer.WriteEndObject(); 
     } 
     writer.WriteEndArray(); 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(List<KeyValuePair<object, object>>); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var jsonObject = JObject.Load(reader); 
     var target = Create(objectType, jsonObject); 
     serializer.Populate(jsonObject.CreateReader(), target); 
     return target; 
    } 

    private object Create(Type objectType, JObject jsonObject) 
    { 
     if (FieldExists("Key", jsonObject)) 
     { 
      return jsonObject["Key"].ToString(); 
     } 

     if (FieldExists("Value", jsonObject)) 
     { 
      return jsonObject["Value"].ToString(); 
     } 
     return null; 
    } 

    private bool FieldExists(string fieldName, JObject jsonObject) 
    { 
     return jsonObject[fieldName] != null; 
    } 
} 

Я зову его из метода WebService как этот

List<KeyValuePair<string, string>> valuesList = new List<KeyValuePair<string, string>>(); 
Dictionary<string, string> valuesDict = SomeDictionaryMethod(); 

foreach(KeyValuePair<string, string> keyValue in valuesDict) 
{ 
    valuesList.Add(keyValue); 
} 

JsonSerializerSettings jsonSettings = new JsonSerializerSettings { Converters = new [] {new KeyValuePairJsonConverter()} }; 
string valuesJson = JsonConvert.SerializeObject(valuesList, jsonSettings); 
+1

Пожалуйста, попробуйте изменить'objectType == typeof (Список >); 'to'objectType == typeof (List >);' in Метод CanConvert –

+4

Один вопрос - почему вы используете список KeyValuePairs вместо словаря? –

+1

@Сергей Березовский вы правы! Наверное, я заблудился, когда искал то, что нужно использовать, и закончил тем, что усложнял ситуацию. Спасибо! – maryhadalittlelamb

ответ

10

Вы можете использовать Newtonsoft и словарь:

var dict = new Dictionary<int, string>(); 
    dict.Add(1, "one"); 
    dict.Add(2, "two"); 

    var output = Newtonsoft.Json.JsonConvert.SerializeObject(dict); 

Выход это:

{"1":"one","2":"two"} 

Редактировать

Благодаря @Sergey Березовском для информации.

Вы используете Newtonsoft, поэтому просто измените свой List<KeyValuePair<object, object>> на Dictionary<object,object> и используйте метод сериализации и десериализации из пакета.

+1

Он уже использует Newtonsoft –

+0

Так что ему просто нужно изменить List > в Dictionnary <объект, объект>. Я отредактирую мой anwser – OrcusZ

+1

Вот что я спросил у него в комментариях. Не всегда возможно изменить список KeyValuePairs для словаря. Пример. Вы можете использовать KVP для передачи ключевых значений в качестве альтернативы Tuple или создания класса. И вы можете иметь много пар ключ-значение с одним и тем же ключом. Что не соответствует словарю. –

0

Так что я не хотел использовать ничего, кроме родного C#, чтобы решить аналогичную проблему, и для справки это использовало .net 4, jquery 3.2.1 и backbone 1.2.0.

Мои проблемы заключались в том, что List<KeyValuePair<...>> будет обрабатывать контроллер в базовой модели, но когда я сохранил эту модель, контроллер не смог связать List.

public class SomeModel { 
    List<KeyValuePair<int, String>> SomeList { get; set; } 
} 

[HttpGet] 
SomeControllerMethod() { 
    SomeModel someModel = new SomeModel(); 
    someModel.SomeList = GetListSortedAlphabetically(); 
    return this.Json(someModel, JsonBehavior.AllowGet); 
} 

сеть захват:

"SomeList":[{"Key":13,"Value":"aaab"},{"Key":248,"Value":"aaac"}] 

Но даже если этот набор SomeList должным образом в поддержке model.js пытается сохранить модель без каких-либо изменений в него может вызвать связывание объекта SomeModel иметь то же самое длина в качестве параметров в теле запроса, но все ключи и значения были нуль:

[HttpPut] 
SomeControllerMethod([FromBody] SomeModel){ 
    SomeModel.SomeList; // Count = 2, all keys and values null. 
} 

Единственное, что я мог бы найти, что KeyValuePair является структурой, а не что-нибудь g, которые могут быть созданы таким образом. То, что я в конечном итоге делает это следующим образом:

  • Добавить модель обертку где-то, что содержит ключ, поля значений:

    public class KeyValuePairWrapper { 
        public int Key { get; set; } 
        public String Value { get; set; } 
    
        //default constructor will be required for binding, the Web.MVC binder will invoke this and set the Key and Value accordingly. 
        public KeyValuePairWrapper() { } 
    
        //a convenience method which allows you to set the values while sorting 
        public KeyValuePairWrapper(int key, String value) 
        { 
         Key = key; 
         Value = value; 
        } 
    } 
    
  • Настройка модели связывания класса, чтобы принять ваш пользовательский объект-оболочку.

    public class SomeModel 
    { 
        public List<KeyValuePairWrapper> KeyValuePairList{ get; set }; 
    } 
    
  • Получить некоторые данные JSon из контроллера

    [HttpGet] 
    SomeControllerMethod() { 
        SomeModel someModel = new SomeModel(); 
        someModel.KeyValuePairList = GetListSortedAlphabetically(); 
        return this.Json(someModel, JsonBehavior.AllowGet); 
    } 
    
  • Сделайте что-нибудь в более позднее время, может быть, model.save (нуль, ...) вызывается

    [HttpPut] 
    SomeControllerMethod([FromBody] SomeModel){ 
        SomeModel.KeyValuePairList ; // Count = 2, all keys and values are correct. 
    } 
    
Смежные вопросы