WebService からカスタム クラスのインスタンスを返すときのシリアル化には、どのようなオプションがありますか?
使用法に応じて設定される場合とされない場合があるその他のプロパティと同様に、いくつかの子コレクション クラス プロパティを持ついくつかのクラスがあります。これらのオブジェクトは、ScriptService 属性で装飾された ASP.NET .asmx WebService から返されるため、さまざまな WebMethods によって返されるときに JSON シリアル化によってシリアル化されます。
問題は、すぐに使用できるシリアライゼーションが、使用されているかどうかに関係なく、すべてのパブリック プロパティを返し、クラス名やその他の情報を、必要な量を制限したい場合よりも詳細な方法で返すことです。トラフィック。
現在、返されるクラスに対して、JSON シリアル化を処理するカスタム JavaScript コンバーターを追加し、以下のように web.config に追加しました。
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization>
<converters>
<add name="CustomClassConverter" type="Namespace.CustomClassConverter" />
</converters>
</jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>
ただし、これにはクラスごとにカスタム コンバーターが必要です。サービスを拡張したり、カスタムシリアライザーを作成したりして、すぐに使用できる JSON シリアライゼーションを変更する他の方法はありますか?
フォローアップ
@marxidad:
他のアプリケーションで DataContractJsonSerializer クラスを使用していますが、これらのサービスに適用する方法がわかりません。サービスのセットアップ方法の例を次に示します。
[ScriptService]
public class MyService : System.Web.Services.WebService
{
[WebMethod]
public CustomClass GetCustomClassMethod
{
return new customClass();
}
}
WebMethods は JavaScript によって呼び出され、JSON でシリアル化されたデータを返します。シリアライゼーションを変更できる唯一の方法は、上記のように JavaScript コンバーターを使用することですか?
WebService にカスタム DataContractJsonSerializer を使用するように指示する方法はありますか? web.config 構成、属性によるサービスの装飾などによるものでしょうか?
更新
さて、上記のように個々の JavaScriptConverters を作成する以外に、すぐに使用できる JavaScriptSerializer を切り替える方法を見つけることができませんでした。
そのために、別のコンバーターを作成する必要がないようにするために行ったことは、汎用の JavaScriptConverter を作成することでした。処理したいクラスに空のインターフェイスを追加し、Web サービスの起動時に呼び出される SupportedTypes はリフレクションを使用して、次のようなインターフェイスを実装する型を見つけます。
public override IEnumerable<Type> SupportedTypes
{
get
{
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
AssemblyBuilder dynamicAssemblyCheck = assembly as AssemblyBuilder;
if (dynamicAssemblyCheck == null)
{
foreach (Type type in assembly.GetExportedTypes())
{
if (typeof(ICustomClass).IsAssignableFrom(type))
{
yield return type;
}
}
}
}
}
}
実際の実装は少し異なり、型がキャッシュされるため、空のインターフェイスではなくカスタム属性を使用するようにリファクタリングする可能性があります。
ただし、これにより、カスタム コレクションを扱うときに、少し異なる問題に遭遇しました。これらは通常、一般的なリストを拡張するだけですが、List<> 自体の代わりにカスタム クラスが使用されます。これは、通常、コレクション クラスにカスタム ロジック、並べ替えなどがあるためです。
問題は、JavaScriptConverter の Serialize メソッドが、JSON にシリアル化された辞書を、関連付けられた型の名前と値のペアとして返すのに対し、リストは配列として返されることです。そのため、コンバーターを使用してコレクション クラスを簡単にシリアル化することはできませんでした。これに対する解決策は、これらの型をコンバーターの SupportedTypes に含めず、リストとして完全にシリアル化することでした。
したがって、シリアライゼーションは機能しますが、これらのオブジェクトを Web サービス呼び出しのパラメーターとして別の方法で渡そうとすると、デシリアライゼーションが中断されます。これは、入力を文字列/オブジェクト ディクショナリのリストとして扱うことができないためです。コレクションに含まれるカスタム クラスのリストに変換されません。これに対処する唯一の方法は、文字列/オブジェクト辞書のリストであるジェネリック クラスを作成し、そのリストを適切なカスタム コレクション クラスに変換し、代わりにジェネリック クラスを使用するように Web サービス パラメーターを変更することです。 .
ここには多くの問題や「ベスト プラクティス」の違反があると思いますが、大量のカスタム コンバーター クラスを作成しなくても問題は解決します。