【问题标题】:JSON.NET Serialiser for Web API (mvc5)用于 Web API 的 JSON.NET 序列化程序 (mvc 5)
【发布时间】:2016-06-26 10:08:44
【问题描述】:

我添加了一个 TypeFormatter,以便使用 JSON.NET 作为 Web api 操作的主要序列化器/反序列化器。

鉴于这个简单的动作

 [HttpPost]
 [Route("api/myentity/")]
 public async Task<HttpResponseMessage> CreateMyEntity(MyEntity entity)
 {
     // .. stuff to add
     // return 200, with some additional info
     return ResultOk(new {status = "Yay, added"});
 }

然后是 JSON.net 类型格式化程序(也添加到配置中)

    public JsonSerializer Serializer { get; private set; }

    /// <summary>
    /// Specify the media types that this MediaTypeFormatter handles
    /// </summary>
    public JsonNetMediaTypeFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json") { CharSet = "utf-8" });
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/json") { CharSet = "utf-8" });

        Serializer = new JsonSerializer
        {
            TypeNameHandling = TypeNameHandling.Objects,
            NullValueHandling = NullValueHandling.Ignore
        };
    }

    public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
    {
        return readStream.ReadAsJson(type, Serializer);
    }

    public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, System.Net.TransportContext transportContext)
    {
        return writeStream.WriteAsJson(value, Serializer);
    }

使用以下模型调用api操作时:

application/json

{
    "Name":"ACME",
    "Phone":"0123456"
} 

(内容没有区别)

我收到了Unexpected token while deserializing object: EndObject. Path '', line 4, position 2.

在其他请求中,有趣的是 JSON.net 总是在 JSON 的最后一个字符之后报告行和字符(在本例中为第 4 行 == "}")

我在序列化程序配置中缺少什么?

谢谢

【问题讨论】:

  • 默认使用 JSON.net。您不需要为此定义自定义媒体类型格式化程序。 source
  • 你知道如何更改底层 JSON.NEt 序列化器的NullValueHandling 吗?
  • 是的,在下面的答案中添加了一个示例

标签: c# asp.net asp.net-mvc asp.net-web-api json.net


【解决方案1】:

Web Api 中默认使用 JSON.net。 NullValueHandling可以在SerializerSettings中配置:

public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
        config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
    }

【讨论】:

    【解决方案2】:

    我不是在问你为什么要实现自己的媒体类型格式化程序,我想你有自己的理由。你能告诉我你从哪里得到 ReadAsJson 扩展方法吗?

    我发现了这个实现StreamExtension,我认为 obj.GetType().IsSubclassOf(instanceType) 有一个小错误。这个表达式永远不会是真的,反序列化的第二次尝试使用将被消耗到最后的流......

    我做了一个小测试,和你面临的一样的例外......

    class Foo
    {
        public string Test { get; set; }
    }
    
    public static Stream ToStream(string str)
    {
        MemoryStream stream = new MemoryStream();
        StreamWriter writer = new StreamWriter(stream);
        writer.Write(str);
        writer.Flush();
        stream.Position = 0;
        return stream;
    }
    
    
    static void Main(string[] args)
    {
        var stream = Program.ToStream(@"{ ""Test"" : ""TesT"" }");
    
        using (var reader = new JsonTextReader(new StreamReader(stream)))
        {
            var serializer = new JsonSerializer
            {
                TypeNameHandling = TypeNameHandling.Objects,
                NullValueHandling = NullValueHandling.Ignore
            };
    
            var obj = serializer.Deserialize(reader);
    
            //  We want to try deserialization without specifying an explicit type first,
            //  then see if the resulting type is compatible with the type that is expected
            //  from the Web API stack stream.
            //  If not, then we try to read it again using an explicit type
            //  (although it probably won't work anyway still :p)
    
            var test = obj.GetType().IsSubclassOf(typeof(Foo)) ? obj : serializer.Deserialize(reader, typeof(Foo));
        }
    

    所以解决方案是实现你自己的反序列化方法,你可以使用我的例子作为开始,简单地将预期类型添加到反序列化方法中,当然去掉 finall 测试......

    var obj = serializer.Deserialize(reader, TYPE);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-24
      • 2016-12-23
      • 1970-01-01
      • 2015-11-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多