2

サードパーティの REST サービスを呼び出す ac#.dotNet プロジェクトに取り組んでいます。

サンプルクラス構造:

[Serializable]
[DataContract(Name = "MainClass")]
[KnownType(typeof(Class1))]
[KnownType(typeof(Class2))]
public class MainClass : IMainInterface
{

    public MainClass()
    {
        Value2 = new List<IClass2>();
    }

    [DataMember(Name = "class")]
    public IClass1 Value1 { get; set; }

    [DataMember(Name = "classes")]
    public List<IClass2> Value2 { get; set; }

}

[Serializable]
[Export(typeof(IClass1))]
[ExportMetadata("IClass1", "Class1")]
[DataContract(Name = "class1")]
public class Class1 : IClass1
{
    [ImportingConstructor]
    public Class1()
    {

    }

    [DataMember(Name = "prop1")]
    public string Prop1 { get; set; }

    [DataMember(Name = "prop2")]
    public string Prop2 { get; set; }

    [DataMember(Name = "prop3")]
    public string Prop3 { get; set; }

}

[Serializable]
[Export(typeof(IClass2))]
[ExportMetadata("IClass2", "Class2")]
[DataContract]
public class Class2 : IClass2
{
    [ImportingConstructor]
    public Class2()
    { }


    [DataMember(Name = "propA")]
    public string PropA { get; set; }

    [DataMember(Name = "propB")]
    public string PropB { get; set; }

    [DataMember(Name = "propC")]
    public string PropC { get; set; }
}

public interface IMainInterface
{
    IClass1 Value1 { get; set; }

    List<IClass2> Value2 { get; set; }
}

public interface IClass1
{
    string Prop1 { get; set; }

    string Prop2 { get; set; }

    string Prop3 { get; set; }
}

public interface IClass2
{
    string PropA { get; set; }

    string PropB { get; set; }

    string PropC { get; set; }
}

Json_String1 : (型ヒント付き)

{
"class":
    {"__type":"class1:#WpfApplication1","prop1":"TestVal0","prop2":"TestVal2","prop3":"TestVal3"},
"classes":
    [
        {"__type":"Class2:#WpfApplication1","propA":"A","propB":"B","propC":"C"},
        {"__type":"Class2:#WpfApplication1","propA":"X","propB":"Y","propC":"Z"},
        {"__type":"Class2:#WpfApplication1","propA":"1","propB":"2","propC":"3"}
    ]
}

Json_String2 : (型ヒントなし)

{
"class":
    {"prop1":"TestVal0","prop2":"TestVal2","prop3":"TestVal3"},
"classes":
    [
        {"propA":"A","propB":"B","propC":"C"},
        {"propA":"X","propB":"Y","propC":"Z"},
        {"propA":"1","propB":"2","propC":"3"}
    ]
}

したがって、特定のクラス構造に対して、をMainClass使用して (のオブジェクトの) json を生成すると、 Json_String1DataContractJsonSerializerが取得され、直接逆シリアル化すると正常に動作します。

一方、データをGETしている間、応答はJson_String2 (型ヒントなし) です。したがって、デシリアライズ中に次のエラーが発生します。

無効なキャスト例外

InvalidCastException が処理されませんでした。タイプ 'System.Object' のオブジェクトをタイプ 'WpfApplication1.IClass2' にキャストできません。

ここで、型ヒントを追加して上記の json (文字列操作) を手動で変更し、正常に逆シリアル化する必要があります。

質問 1) デシリアライズのためにこの Json 文字列操作を回避するにはどうすればよいですか?

質問 2) タイプヒントなしで json を作成するにはどうすればよいですか?

edit : 1. MainClassによって実装されるIMainInterfaceを追加しました。2. dotNet フレームワーク 4

4

2 に答える 2

0

問題は、インターフェイスのみを持つクラスに逆シリアル化しようとしているためです。JSON で __type が指定されている場合は、明らかに機能します。しかし、そうでない場合 (2 番目の JSON の例のように)、ReadObject はインターフェイスを実装に自動的に解決できません。

インターフェイス (IClass1、IClass2) の代わりに具象クラスを使用してみてくださいClass1。コードの残りの部分はそのままでかまいません。両方の Json の例は、これで正常に動作するはずです。Class2MainClass

[Serializable]
[DataContract(Name = "MainClass")]
[KnownType(typeof(Class1))]
[KnownType(typeof(Class2))]
public class MainClass
{

    public MainClass()
    {
        Value2 = new List<Class2>();
    }

    [DataMember(Name = "class")]
    public Class1 Value1 { get; set; }

    [DataMember(Name = "classes")]
    public List<Class2> Value2 { get; set; }

}
于 2015-01-11T13:57:15.007 に答える