用于Web API的JSON.NET Serialiser(mvc5)

时间:2016-06-26 10:08:45

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

我添加了一个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行==&#34;}&#34;)

我在serialiser配置中缺少什么?

感谢

2 个答案:

答案 0 :(得分:2)

默认情况下,Web Api中使用JSON.net。可以在NullValueHandling

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

答案 1 :(得分:1)

我不是在问你为什么要实现自己的媒体类型格式化程序,我有你自己的理由。你能告诉我你在哪里获得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));
    }

所以解决方案就是实现你自己的反序列化方法,你可以使用我的例子作为start并简单地将期望的类型添加到反序列化方法,并删除finall测试当然...

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