1

鉴于 JSON 文本无效,{ "foo" = "bar" }ServiceStack 内置的 JSON 反序列化器将成功将其解码为以下 DTO:

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

现在,也许这对于某些用例来说是可以接受的,因为它看起来有点像 C# 初始化程序,所以实际上可能不解析 JSON 是这个库的一个特性。

但是,当给定无效的 JSON 文本时{ "foo" xxx "bar" },不会引发任何错误,而且可怕的是 Foo 属性设置为“xxx”。

有没有办法(a)将 ServiceStack.Text 配置为仅解析 JSON(而不是默认情况下接受的任何非标准变体)或(b)在应用程序级别用 JSON.NET 替换序列化程序?

编辑:看起来 ServiceStack 的 Web 路由代码的反序列化行为与在无效解析ServiceState.Text.JsonSerializer时返回的行为不同。default(T)

编辑2(进度?):

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

设置此选项将导致 ServiceStack 在格式错误的 JSON 上返回 400 Bad Request,但遗憾的是无法将 JSON 反序列化为给定的 DTO。也许这是解决方案的一部分?

解决方案:

用自定义的“application/json”处理程序替换 ServiceStack 的默认 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 序列化程序,包装了出色的 JSON.NET 库。此解决方案在无效 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您可以设置为(我不true知道默认值是否为false)并查看其行为方式。

于 2014-03-24T00:15:39.643 回答