特に複雑なオブジェクトを表すクラスのセットを作成しようとしていますが、それらのクラスの1つに、3つの可能な派生クラスの基本(抽象)クラスとして設定されたプロパティがあります。シリアル化と逆シリアル化を処理するようにASP.NETWebAPIを設定しています。つまり、デフォルトでは、JSONにJson.NETを使用します。POSTまたはPUTを介して送信されたJSONを適切な派生クラスに適切に逆シリアル化するようにWebAPIを取得するにはどうすればよいですか?
抽象メンバーを持つクラスは次のようになります(明確にするため、およびXmlSerializerを使用してxmlを逆シリアル化するために完全に機能するため、Xmlデコレーターを含めています)
[Serializable]
public class FormulaStructure {
[XmlElement("column", typeof(ColumnStructure))]
[XmlElement("function", typeof(FunctionStructure))]
[XmlElement("operand", typeof(OperandStructure))]
public AFormulaItemStructure FormulaItem;
}
抽象クラスはかなり基本的です:
[Serializable]
public abstract class AFormulaItemStructure { }
そして、抽象クラスには3つの派生物があります。
[Serializable]
public class ColumnStructure: AFormulaItemStructure {
[XmlAttribute("type")]
public string Type;
[XmlAttribute("field")]
public string Field;
[XmlAttribute("display")]
public string Display;
}
[Serializable]
public class FunctionStructure: AFormulaItemStructure {
[XmlAttribute("type")]
public string Type;
[XmlAttribute("name")]
public string Name;
[XmlElement("parameters")]
public string Parameters;
}
[Serializable]
public class OperandStructure: AFormulaItemStructure {
[XmlAttribute("type")]
public string Type;
[XmlElement("left")]
public string Left;
[XmlElement("right")]
public string Right;
}
現在、[DataContract]
属性を使用すると、Json.NETフォーマッターは派生クラスへの入力に失敗し、プロパティを残しますnull
。
質問
同じクラスのXmlSerializer
属性と属性 を混在させることはできますか?設計したxmlでxml属性を 使用しているため使用していますが、xmlスキーマを自分で開発しているため、必要に応じて変更できます。DataContractSerializer
XmlSerializer
Json.NETで同等のものは何 [KnownType()]
ですか?DataContractSerializer
Json.NETはのバージョンを尊重していないようですKnownType
。適切なタイプを決定するために、自分のJsonConverterをロールする必要がありますか?
XmlとJsonの両方でオブジェクトを適切に逆シリアル化するように、DataContractSerializer
または適切に逆シリアル化する ように、クラスをどのように装飾しますか? 私の目標は、これをASP.NET Web APIに組み込むことです。そのため、要求されたタイプに応じて、XmlまたはJsonを柔軟に生成できるようにします。Json.NETが機能しない場合、この複雑なクラスを操作するために使用する必要のある代替フォーマッターはありますか?DataContractJsonSerializer
必ずしも.NETクラス名をオブジェクトに含めずに、クライアント側でオブジェクトを生成する機能が必要です。
テストと改良
Web APIのテストでは、デフォルトのシリアル化がクライアントに送信されます。
{"FormulaItem":{"type":"int","field":"my_field","display":"My Field"}}
これは私の目的にとって理想的です。ただし、これをAPIに戻し、適切な派生型に逆シリアル化することは機能しません(プロパティに対してnullを生成します)。
以下のTommyGrovnesの回答をテストすると、彼DataContractSerializer
はテストに使用して次のように生成します。
{"FormulaItem":{"__type":"column:#ExpressionStructureExperimentation.Models","display":"My Field","field":"my_field","type":"int"}}
これは私にとってもコードの保守性にとっても機能しません(これらのオブジェクトを生成するために名前空間全体をJavaScriptにハードコーディングすると、リファクタリングはPITAになります)。