14

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 サービス パラメーターを変更することです。 .

ここには多くの問題や「ベスト プラクティス」の違反があると思いますが、大量のカスタム コンバーター クラスを作成しなくても問題は解決します。

4

5 に答える 5

2

このスレッドがしばらく静かだったことは知っていますが、カスタム コンバーターで JavaScriptConverter の SupportedTypes プロパティをオーバーライドする場合は、コンバーターを使用する必要がある型を追加できることを提案したいと思います。これは、必要に応じて構成ファイルに入れることができます。そうすれば、クラスごとにカスタム コンバーターは必要ありません。

汎用コンバーターを作成しようとしましたが、web.config でそれを識別する方法がわかりませんでした。他の誰かがそれを管理したかどうかを知りたいです。

上記の問題を解決しようとしたときにアイデアが浮かび、Nick Berardi の「より正確な JSON .NET シリアライザーの作成」(google it) に出くわしました。

私のために働いた:)

ありがとうございます。

于 2009-06-01T05:31:15.710 に答える
2

コード生成クラスを使用しない場合は、プロパティをScriptIgnoreAttributeで修飾して、特定のプロパティを無視するようにシリアライザーに指示できます。Xml シリアライゼーションにも同様の属性があります。

もちろん、1 つのサービス メソッド呼び出しでクラスのいくつかのプロパティを返し、別のサービス メソッド呼び出しで同じクラスの異なるプロパティを返したい場合、このアプローチは使用できません。そのためには、サービス メソッドで匿名型を返します。

[WebMethod]
[ScriptMethod]
public object GimmieData()
{
    var dalEntity = dal.GimmieEntity(); //However yours works...

    return new
       {
           id = dalEntity.Id,
           description = dalEntity.Desc
       };

}

シリアライザは、オブジェクトをテキストに変換するだけなので、送信するオブジェクトのタイプはあまり気にしません。

また、シリアル化プロセスをきめ細かく制御するために、データ エンティティに ISerializable を (コード生成されたデータ エンティティがある場合は部分クラスとして) 実装できると思いますが、試したことはありませ

于 2009-04-29T14:30:03.843 に答える
1

.NET 3.x を使用している (または使用できる) 場合は、WCF サービスが最適です。

[DataMember] 属性を使用して、クライアントにシリアル化されるプロパティを選択的に制御できます。WCF では、必要に応じて、JSON のシリアル化と逆シリアル化をよりきめ細かく制御することもできます。

これは、開始するための良い例です: http://blogs.msdn.com/kaevans/archive/2007/09/04/using-wcf-json-linq-and-ajax-passing-complex-types-to-wcf -services-with-json-encoding.aspx

于 2008-10-14T06:03:33.613 に答える
0

アセンブリでSystem.Runtime.Serialization.Json.DataContractJsonSerializerクラスを使用できます。System.ServiceModel.Web.dll

于 2008-10-01T21:20:41.187 に答える
0

確かにこれが機能していることについて私を引用しないでください、しかし私はこれがあなたが探しているものであると信じています。

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public XmlDocument GetXmlDocument()
{
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(_xmlString);
    return xmlDoc;
}
于 2008-10-01T21:49:21.320 に答える