web-dev-qa-db-ja.com

DataContractJsonSerializerの逆シリアル化の問題

次のJSONを取得しました。

[{
    "name": "numToRetrieve",
    "value": "3",
    "label": "Number of items to retrieve:",
    "items": {
        "1": "1",
        "3": "3",
        "5": "5"
    },
    "rules": {
        "range": "1-2"
    }
},
{
    "name": "showFoo",
    "value": "on",
    "label": "Show foo?"
},
{
    "name": "title",
    "value": "Foo",
    "label": "Foo:"
}]

オールインワンバージョン(文字列リテラルに適しています):

[{\"name\":\"numToRetrieve\",\"value\":\"3\",\"label\":\"Number of items to retrieve:\",\"items\":{\"1\":\"1\",\"3\":\"3\",\"5\":\"5\"},\"rules\":{\"range\":\"1-2\"}},{\"name\":\"showFoo\",\"value\":\"on\",\"label\":\"Show foo?\"},{\"name\":\"title\",\"value\":\"Foo\",\"label\":\"Foo:\"}]

上記の例では、namevalue、およびlabelは必須ですが、itemsおよびrulesはオプションです。

これが私がデシリアライズしようとしているクラスです:

using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace foofoo
{
    [DataContract]
    public sealed class FooDef
    {
        [DataMember(Name = "name", IsRequired = true)]
        public string Name { get; set; }

        [DataMember(Name = "value", IsRequired = true)]
        public string Value { get; set; }

        [DataMember(Name = "label", IsRequired = true)]
        public string Label { get; set; }

        [DataMember(Name = "items", IsRequired = false)]
        public Dictionary<string, string> Items { get; set; }

        [DataMember(Name = "rules", IsRequired = false)]
        public Dictionary<string, string> Rules { get; set; }
    }
}

これが、逆シリアル化に使用するコードです。

var json = new DataContractJsonSerializer(typeof(List<FooDef>));
var bar = "[{\"name\":\"numToRetrieve\",\"value\":\"3\",\"label\":\"Number of items to retrieve:\",\"items\":{\"1\":\"1\",\"3\":\"3\",\"5\":\"5\"},\"rules\":{\"range\":\"1-2\"}},{\"name\":\"showFoo\",\"value\":\"on\",\"label\":\"Show foo?\"},{\"name\":\"title\",\"value\":\"Foo\",\"label\":\"Foo:\"}]";
var stream = new MemoryStream(Encoding.UTF8.GetBytes(bar));
var foo = json.ReadObject(stream);
stream.Close();

最初のitemsパスでrulesFooDefが空であることを除いて、すべてが問題なくうまくいきます。私はSunの下ですべてを試し、それらを設定してみました:カスタムクラス、NameValueCollectionKeyValuePair<string, string>List後者の両方、および適用されると思われる他のすべてのコレクション。 [編集:Hashtableを試すのを忘れました。これは明らかな候補のように見えました。うまくいきませんでした。]

私が見るように、問題はitemsrulesの下の重要な部分が制限されていないことです。つまり、常にrangeまたは3と呼ばれるわけではありません。何かアドバイスやアイデアはありますか?

22
bbrown

IMHO DataContractJsonSerializerを使用して.NETクラスに提供したJSON文字列を逆シリアル化する方法はありません。

問題は DataContractJsonSerializer 辞書をシリアル化する方法に起因します。 Json.NET (私が強くお勧めします)または JavaScriptSerializer (DataContractJsonSerializerを支持して非推奨になったと思いますが、シナリオで機能します)などの代替シリアライザーを使用できます)。

theserants と読むこともできます。

ドキュメント:コレクションのシリアル化-Json.NET

22
Darin Dimitrov

http://social.msdn.Microsoft.com/Forums/en-US/wcf/thread/071f73bb-e141-4a68-ae61-05635382934f

この記事をチェックしてください。私の問題はほぼ完全に解決されました。私はそれらのオブジェクト[]タイプを文字列に変更する必要がありましたが、私はstrings:stringタイプのキー/値のペアのみを使用しているため、問題はありません。

7
Sean Kelly