1

無効な JSON テキスト が与えられた場合、{ "foo" = "bar" }ServiceStack に組み込まれている JSON デシリアライザーは、これを次の DTO に正常にデコードします。

public class FooDto {
   public string Foo { get; set; }
}

これは、C# のイニシャライザーのように見えるため、一部のユース ケースでは許容される可能性があります。JSON を実際に解析しないことは、このライブラリの機能です。

ただし、無効な JSON テキストを指定すると{ "foo" xxx "bar" }、エラーはスローされず、恐ろしいことに Foo プロパティが「xxx」に設定されます。

(a) JSON のみを解析するように ServiceStack.Text を構成する方法 (デフォルトで受け入れられる非標準のバリアントではなく)、または (b) アプリケーション レベルでシリアライザーをたとえば JSON.NET に置き換える方法はありますか?

編集: また、Web ルーティング コードに対する ServiceStack の逆シリアル化動作は、無効な解析でServiceState.Text.JsonSerializer返されるように見える動作とは異なるように見えます。default(T)

編集 2 (進行状況?):

appHost.SetConfig(new HostConfig { UseBclJsonSerializers = true });

このオプションを設定すると、ServiceStack は不正な形式の JSON に対して 400 Bad Request を返しますが、残念ながら JSON を指定された DTO に逆シリアル化することはできません。多分これは解決策の一部ですか?

解決:

ServiceStack のデフォルトの JSON シリアライザーをカスタムの "application/json" ハンドラーに置き換えて、JSON.NET シリアライザーをラップすると、問題が解決しました。以下の回答にソリューションコードのコピーを含めました。お役に立てば幸いです。

4

3 に答える 3

3

wiki ドキュメントには、独自のカスタム メディア タイプを登録する方法が記載されています。これは、ServiceStack の組み込み形式よりも優先されます。

ServiceStack に登録して、AppHost で別のシリアライザーを使用するには、次のようにします。

this.ContentTypes.Register(MimeTypes.Json, 
    serialize: (IRequest req, object response, Stream stream) => ..., 
    deserialize: (Type type, Stream stream) => ...);  
于 2014-03-24T00:45:59.813 に答える
3

最終的に、優れた JSON.NET ライブラリをラップするカスタム JSON シリアライザーを作成しました。このソリューションでは、無効な JSON で例外が発生するため、予想どおり 400 Bad Request が返されます。

警告: この実装は、Accept-Charset ヘッダーと Content-Type ヘッダーの charset パラメーターを無視し、代わりに UTF8 を想定します。ネットワーク上で UTF8 を想定できない場合は、このコードを微調整する必要があります。

public class UseJsonDotNet : IPlugin
{
    public JsonSerializerSettings Settings { get; set; }

    public void Register(IAppHost appHost)
    {
        appHost.ContentTypes.Register(
            "application/json",
            WriteObjectToStream,
            ReadObjectFromStream);
    }

    public void WriteObjectToStream(
        IRequest request, object response, Stream target)
    {
        var s = JsonConvert.SerializeObject(response, Formatting.None, Settings);
        using (var writer = new StreamWriter(target, Encoding.UTF8, 1024, true))
        {
            writer.Write(s);
        }
    }

    public object ReadObjectFromStream(Type type, Stream source)
    {
        using (var reader = new StreamReader(source, Encoding.UTF8))
        {
            var s = reader.ReadToEnd();
            var o = JsonConvert.DeserializeObject(s, type, Settings);
            return o;
        }
    }
}

それを使用するには、登録するだけです:

Plugins.Add(new UseJsonDotNet { Settings = ... } );
于 2014-03-24T01:20:11.303 に答える
0

JsConfigクラスを見てください。便利な設定項目がいくつかありますが、必要なものが見つかるかどうかはわかりません。(デフォルト値が かどうかはわかりません)にJsConfig.ThrowOnDeserializationError設定して、それがどのように動作するかを確認できます。truefalse

于 2014-03-24T00:15:39.643 に答える