2017-01-06 15 views
6

Jestem bardzo nowy w JSON, pomóż!Lista seriali <KeyValuePair <ciąg, ciąg >> jako JSON

Próbuję serialise List<KeyValuePair<string, string>> jako JSON

Aktualnie

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

Oczekiwany:

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

I, o których mowa kilka przykładów z this i this.

To mój 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; 
    } 
} 

Wołam go z metody WebService jak ten

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

Proszę zmienić "obiekt_typu == typof (Lista >); do" obiekt_typu == typof (Lista >); CanConvert method –

+4

Jedno pytanie - dlaczego używasz listy KeyValuePairs zamiast Dictionary? –

+1

@SergeyBerezovskiy masz rację! Sądzę, że zgubiłem się podczas szukania w Google, co używać i skończyło się na komplikowaniu rzeczy. Dziękuję Ci! – maryhadalittlelamb

Odpowiedz

10

Można użyć Newtonsoft i słownika:

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

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

Wyjście jest:

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

Edit

Dzięki @Sergey Berezovskiy dla informacji.

Aktualnie używasz Newtonsoft, więc po prostu zmień swoje List<KeyValuePair<object, object>> na Dictionary<object,object> i użyj metody serializacji i deserializacji z pakietu.

+1

On już używa Newtonsoft –

+0

Musi tylko zmienić List > na Słownik . Będę edytować mojego anwser'a – OrcusZ

+1

To właśnie zadałem mu w komentarzach. Nie zawsze jest możliwa zmiana listy KeyValuePairs na słownik. Przykład - możesz użyć KVP do przekazania par klucz-wartość jako alternatywy dla Tuple lub tworzenia klasy. Możesz mieć wiele par klucz-wartość z tym samym kluczem. Co nie jest prawdą w słowniku. –

0

Tak więc nie chciałem używać niczego oprócz natywnego C# do rozwiązania podobnego problemu i dla odniesienia było to używanie .net 4, jquery 3.2.1 i szkieletu 1.2.0.

Moje problemy polegały na tym, że List<KeyValuePair<...>> byłby przetwarzany poza kontroler w model szkieletowy, ale kiedy zapisałem ten model, kontroler nie mógł powiązać 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); 
} 

przechwytywania sieci:

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

Ale choć ten zestaw jakaśLista właściwie w podłożu model.js próbują zapisać model bez zmian spowodowałoby to wiązanie obiekt SomeModel mieć takie same długość jako parametrów w organizmie żądanie, ale wszystkie klucze i wartości były zerowy:

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

Jedyne co mogę znaleźć jest to, że KeyValuePair jest strukturą, a nie coś g, który można utworzyć w ten sposób. Co skończyło się robi jest następujący:

  • Dodaj owijkę modelu gdzieś, że zawiera kluczowe, pola wartości:

    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; 
        } 
    } 
    
  • Skonfiguruj wiążącej modelu klasy, aby zaakceptować obiekt niestandardowy otoki.

    public class SomeModel 
    { 
        public List<KeyValuePairWrapper> KeyValuePairList{ get; set }; 
    } 
    
  • Trochę danych json z kontrolerem

    [HttpGet] 
    SomeControllerMethod() { 
        SomeModel someModel = new SomeModel(); 
        someModel.KeyValuePairList = GetListSortedAlphabetically(); 
        return this.Json(someModel, JsonBehavior.AllowGet); 
    } 
    
  • coś zrobić w późniejszym czasie może model.save (null, ...) jest wywoływana

    [HttpPut] 
    SomeControllerMethod([FromBody] SomeModel){ 
        SomeModel.KeyValuePairList ; // Count = 2, all keys and values are correct. 
    } 
    
Powiązane problemy