web-dev-qa-db-ja.com

List <KeyValuePair <string、string >>をJSONとしてシリアル化します

私は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);
17

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 Berezovskiyに感謝します。

現在、Newtonsoftを使用しているため、List<KeyValuePair<object, object>>からDictionary<object,object>そして、パッケージのserializeおよびdeserializeメソッドを使用します。

25
OrcusZ

したがって、同様の問題を解決するためにネイティブc#以外は使用したくありませんでした。参考として、これは.net 4、jquery 3.2.1、およびバックボーン1.2.0を使用していました。

私の問題は、List<KeyValuePair<...>>はコントローラーからバックボーンモデルに処理されますが、そのモデルを保存すると、コントローラーはリストをバインドできませんでした。

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"}]

ただし、モデルを変更せずにモデルを保存しようとすると、backing model.jsでSomeListが適切に設定されますが、バインディングSomeModelオブジェクトの長さはリクエスト本文のパラメーターと同じになりますが、すべてのキーと値はnullになります。

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

私が見つけることができる唯一のことは、KeyValuePairが構造であり、この方法でインスタンス化できるものではないということです。私がやったことは次のとおりです:

  • キー、値フィールドを含むモデルラッパーをどこかに追加します。

    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(null、...)が呼び出される

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