4

シンプルなインターフェースがあるとしましょう:

public interface ISerialize
    {
        string FirstProp { get; set; }
        string SecondProp { get; set; }

    }

それはクラスによって実装されます:

   public class Class1 : ISerialize
   {
        public string FirstProp { get; set; }
        public string SecondProp { get; set; }
        public string ThirdProp { get; set; }
   }
    public class Class2 : ISerialize
    {
         public string FirstProp { get; set; }
         public string SecondProp { get; set; }
         public string FourthProp { get; set; }
    }

現時点では (これは長期的な安定性を意図したものではありません)、次のような Web ページがあります: http://jsfiddle.net/SBbPT/ここで、各テキスト ボックスは Class1 または Class2 オブジェクトのプロパティに対応し、Add to batchリンクはオブジェクトに JavaScript 配列を追加し、Submit batchボタンは JSON 文字列を文字列化されたオブジェクトの Web サービスに送信します。当分の間、次の JS がどのタイプClass1またはClass2作成されるかを決定します。

 $(document).ready(function ()
        {
            var iSerialize = [];
            $('#btnSubmit').click(function ()
            {
                //creates Class1 object if ThirdProp is present
                if ($('#txt3').val().length > 0)
                {
                    var class1 = { FirstProp: $('#txt1').val(), SecondProp: $('#txt2').val(), ThirdProp: $('#txt3').val() }
                    iSerialize.push(class1);
                }
                else
                {
                    var class2 = { FirstProp: $('#txt1').val(), SecondProp: $('#txt2').val(), FourthProp: $('#txt4').val() };
                    iSerialize.push(class2);
                }
                $('input').val('');
            });
            $('#btnSubmitBatch').click(function ()
            {
                var data = "{jsonString:'" + JSON.stringify(iSerialize) + "'}";
                console.log(data);
                $.ajax(
                {
                    type: "POST",
                    url: "default.aspx/DataList",
                    contentType: "application/json",
                    dataType: "json",
                    data: data,
                    success: function (data)
                    {
                        console.log('the post was successful');
                        console.log(data.d);
                    },
                    error: function (xhr)
                    {
                        console.log(xhr.status);
                    }
                });
            });

        });

現在、ユーザーが FourthProp テキスト ボックスを空白のままにすると Class1 オブジェクトが作成され、ユーザーが ThirdProp テキスト ボックスを空白のままにすると Class2 オブジェクトが作成されます。現在の Web サービス メソッドは次のようになります。

[WebMethod]
        public string DataList(string jsonString)
        {
            var jss = new JavaScriptSerializer();
            List<ISerialize> list = jss.Deserialize<List<ISerialize>>(jsonString);
            //some members might have different properties
            //how to create a factory to create an instance based on the objects properties?
            return list[0].FirstProp;
        }

現在の状態ではエラーが発生します。No parameterless constructor defined for type of DeserializeListOfInterfaceTypes.ISerialize. これは回避できList<ISerialize>、具体的な型の 1 つのリストを作成することでプログラムが機能します。したがって、この場合、プロパティThirdProporの存在によってFourthProp、オブジェクトがClass1またはClass2である必要があるかどうかがそれぞれ決定されます。JavaScript オブジェクトのプロパティを使用して、作成する C# オブジェクトを決定するにはどうすればよいですか?

4

4 に答える 4

2

問題は、デシリアライザーがインターフェイスではなく、クラスをインスタンス化してリストに入力する必要があることです。しかし、どのクラスかを知る方法はありません。

したがって、あなたの質問は次のようになります: 各 JSON オブジェクトに対してどのクラスを作成するかをデシリアライザーに示唆する方法は?

JSON に「クラス」の記述を含める標準的な方法はありません (少なくとも今のところ)。独自のルールを考え出す必要があります (「タイプ」プロパティを含めるか、提案したように既存のプロパティを調べます)。もちろん、JSON フレームワークにはルールを知る方法がないため、「魔法のように」発生することはありません。

シリアル化に Newtonsoft の JSON.net を使用すると仮定します (使用しない場合は使用する必要があります)。この正確な質問は、ここで尋ねられ、回答されました。

JSON.NET でカスタム JsonConverter を実装して、基本クラス オブジェクトのリストを逆シリアル化する方法は?

基本的には、をオーバーライドすることになりますJsonConverter

于 2013-09-13T15:15:12.333 に答える