2017-09-05 10 views
0

データクラスのシリアル化と逆シリアル化が必要な既存のレポートインターフェイス用にリモート接続を実装する必要があります。ここでは、クラスやインタフェースの簡易版は、次のとおりです。入力パラメータとしてJSON Newtonsoft C#異なるタイプのオブジェクトのリストを逆シリアル化する

public interface IBase 
    { 
     string Name { get; } 
    } 

    public interface IDerived1 
    { 
     int Value { get; } 
    } 

    public interface IDerived2 
    { 
     bool Value { get; } 
    } 

    public class Base : IBase 
    { 
     public string Name { get; protected set; } 
    } 

    public class Derived1 : Base, IDerived1 
    { 
     public int Value { get; protected set; } 
    } 

    public class Derived2 : Base, IDerived2 
    { 
     public bool Value { get; protected set; } 
    } 

私は、このコレクションは「Derived1」と「Derived2」の任意の数のインスタンスとの組み合わせを含むことが

IEnumerable<IBase> reportingData 

を取得します。例えば私は、この与え

string serialisedReportingData = JsonConvert.SerializeObject(reportingData); 

:私は、このようなコレクションシリアライズ

を[{ "値":11、 "名": "製品番号が"}、{ "バリュー":偽明らかにこのデータだけでは、個々のコレクションエントリのタイプがJSONにないため、非直列化は不可能です。たとえば、JSONの型部分を作成したり、逆シリアル化中に使用するための型のコレクションを追加したりできます。

シナリオの

JsonConvert.DeserializeObject<IEnumerable<Ixxx>>(...); 

タイプに対処する前に、私はCustomCreationConverterのオーバーロードを使用しているが、これは唯一のIEnumerable内部の単一のインターフェイスタイプに適用されます。上記の私の例では、IDerived1とIDerived2という2つの方法があります。

私の質問/問題:

A)私はCustomCreationConverterが複数のインターフェイスタイプを扱うと、私はこれにタイプを取得する方法がわからないことを書くことができるかわかりません。

b)入力として受け取った 'IEnumerable reportingData'と同じ非直列化出力を与えるソリューションを実装する方法に関するご意見をお待ちしております。

可能であれば、実用的なコード例があります。事前に

多くのおかげで、 クリスチャン

+0

あなたが見る、 '「$種別」'情報を含めない場合(httpsの[基本クラスのオブジェクトのリストをデシリアライズするJSON.NETでカスタムJsonConverterを実装する方法は?]:// stackoverflowの。com/q/8030538)と[json.netを使用して型情報のない多型jsonクラスを逆シリアル化する](https://stackoverflow.com/q/19307752)を参照してください。 – dbc

答えて

1

更新:(DBCからのコメントに触発)

型名をデシリアライズするときは、SerializationBinderを使用する必要があります。 KnownTypesBinderについてはこちらをご覧ください。 (Newtonsoft.Jsonバージョン10以上が必要)

まず、プロパティを設定する場合は、publicにする必要があります。 次に、JsonSerializerSettingsを使用してシリアライズ/デシリアライズすることができます。

List<IBase> loList = new List<IBase>(); 
loList.Add(new Base() { Name = "Base" }); 
loList.Add(new Derived1() { Name = "Derived1", Value = 3 }); 
loList.Add(new Derived2() { Name = "Derived2", Value = true }); 

KnownTypesBinder loKnownTypesBinder = new KnownTypesBinder() 
{ 
    KnownTypes = new List<Type> { typeof(Base), typeof(Derived1), typeof(Derived2) } 
}; 

IEnumerable<IBase> reportingData = loList.AsEnumerable(); 
JsonSerializerSettings loJsonSerializerSettings = new JsonSerializerSettings() 
{ 
    TypeNameHandling = TypeNameHandling.Objects, 
    SerializationBinder = loKnownTypesBinder 
}; 

string lsOut = JsonConvert.SerializeObject(reportingData, loJsonSerializerSettings); 
reportingData = JsonConvert.DeserializeObject<IEnumerable<IBase>>(lsOut, loJsonSerializerSettings); 

このようなJsonSerializerSettingsを使用すると、タイプ情報がjson文字列に含まれます。

[{ 
     "$type": "Base", 
     "Name": "Base" 
    }, { 
     "$type": "Derived1", 
     "Value": 3, 
     "Name": "Derived1" 
    }, { 
     "$type": "Derived2", 
     "Value": true, 
     "Name": "Derived2" 
    } 
] 
+0

'$ type'情報はセキュリティのためにサニタイズする必要があります。詳細については、Newtonsoft Jsonの[TypeName Handling Caution](https://stackoverflow.com/q/39565954)を参照してください。 – dbc

+0

@dbc:Thx。私は私の答えを更新しました。 – PinBack

+0

ありがとうSOOOO!私はその答えがまっすぐであるとは思っていませんでした。私だけでなく、私の同僚の何人かがあなたの知恵をとても高く評価します! :-) – Christian

関連する問題