37

Json.Net は通常、Dictionary<k,v>a をコレクションにシリアル化します。

"MyDict": {
  "Apples": {
    "Taste": 1341181398,
    "Title": "Granny Smith",
  },
  "Oranges": {
    "Taste": 9999999999,
    "Title": "Coxes Pippin",
  },
 }

これは素晴らしいことです。そして、SOを見回すと、ほとんどの人が望んでいるようです。Dictionary<k,v>ただし、この特定のケースでは、代わりに my と Array フォーマットの間でシリアライズしたいと考えています。

"MyDict": [
    "k": "Apples",
    "v": {
        "Taste": 1341181398,
        "Title": "Granny Smith",
    }
  },
    "k:": "Oranges",
    "v:": {
        "Taste": 9999999999,
        "Title": "Coxes Pippin",
    }
  },
]

既存のフィールド タイプでこれを行う簡単な方法はありますか? たとえば、注釈を付けることができる属性はありますか?

4

6 に答える 6

45

これを実現する別の方法は、カスタム を使用することContractResolverです。そうすればDictionary<K,V>、他の回答で示唆されているように、シリアル化するたびにサブクラス化したり、変換を適用したりする必要はありません。

次のリゾルバーは、すべての辞書を「キー」および「値」プロパティを持つオブジェクトの配列としてシリアル化します。

class DictionaryAsArrayResolver : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type objectType)
    {
        if (objectType.GetInterfaces().Any(i => i == typeof(IDictionary) || 
           (i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>))))
        {
            return base.CreateArrayContract(objectType);
        }

        return base.CreateContract(objectType);
    }
}

リゾルバーを使用するには、それを に追加してから、次のようJsonSerializerSettingsに設定を渡します。JsonConvert.SerializeObject()

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new DictionaryAsArrayResolver();

string json = JsonConvert.SerializeObject(obj, settings);

これが実際のデモです。

于 2014-07-31T16:48:37.683 に答える
29

ああ、これは私が望んでいたのと同じくらい簡単であることがわかりました。MyDictionary<k,v>はすでにサブクラス化されており、 で注釈を付けることができることがわかりました[JsonArrayAttribute]。これにより、必要な形式が正確に得られます。

"MyDict": [
  {
    "Key": "Apples",
    "Value": {
        "Taste": 1341181398,
        "Title": "Granny Smith",
    }
  },
  {
    "Key:": "Oranges",
    "Value:": {
        "Taste": 9999999999,
        "Title": "Coxes Pippin",
    }
  },
]
于 2012-10-05T21:57:47.190 に答える
14

この例では、辞書を使用します。

var myDict = new Dictionary<string,string>() { 
    {"a","123"}, 
    {"b","234"}, 
    {"c","345"} 
};

Newtonsoft.Json.JsonConvert.SerializeObject(myDict)(を使用して)次のようにシリアル化します。

{"a":"123","b":"234","c":"345"}

LINQ を使用して変換を実行して匿名オブジェクトを作成し、それをシリアル化できます。

 var myDictTransformed = from key in myDict.Keys
                         select new { k = key, v = myDict[key] };

または、実際のオブジェクトを使用できます

class MyDictEntry 
{
    public string k { get; set; }
    public string v { get; set; }
}

上記または代替の LINQ 構文のいずれか:

var myDictTransformed = myDict.Keys.AsEnumerable()
                        .Select(key => new MyDictEntry{ 
                            k = key, 
                            v = myDict[key] 
                        });

いずれにせよ、これは次のようにシリアル化されます。

[
  {"k":"a", "v":"123"},
  {"k":"b", "v":"234"},
  {"k":"c", "v":"345"}
]

.NET フィドル リンク: https://dotnetfiddle.net/LhisVW

于 2012-10-05T18:33:14.187 に答える
12

私が見つけた最も簡単な解決策は、あなたをに変換するDictionary<string, string>ことList<KeyValuePair<string, string>>です。JSON.NET は次にList、フォームをオブジェクトの配列に変換します{ Key: 'keyname', Value: 'value' }。これは、必要なモデルの変更を受け入れ、サブクラス化したくない場合にうまく機能しますDictionary

于 2015-08-25T01:09:26.560 に答える
1

gregmac の回答は役に立ちましたが、うまくいきませんでした。以下は同じ考えです...駄洒落なし。

var dictionaryTransformed = dictionary.Select(item => item.Key).Select(i => 
                        new {Key = i, Value = dictionary[i] });

またはもちろん

var dictionaryTransformed = dictionary.Select(item => 
                        new {item.Key, Value = dictionary[item.Key] });

次にjsonへ

var json = (new JavaScriptSerializer()).Serialize( 
                        new { Container = dictionaryTransformed.ToArray() } )
于 2012-12-17T23:33:22.590 に答える