web api json反序列化失败

时间:2012-04-25 11:06:55

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

我在web api中使用了一个请求端点:

 public HttpResponseMessage Create(IList<SlideContent> l)
    {
        ...
    }

我将参数作为json发送,web api将其序列化为IList

SlideContent是:

public abstract class SlideItem
    {
       ...
    }

我有专门的课程

    public class TitleSlideItem : SlideItem
    {
        ...
    }


    public class ParagraphSlideItem : SlideItem
    {
       ...
    }

就像我不能调用Create函数一样,因为我得到了一个

  

missingmethodexception:无法创建抽象类

所以我无法反序列化json参数。如果我删除抽象修饰符,那么我没有专门的对象,每个对象的类型将是SlideContent。 我甚至在json中添加了注释,但它也没有帮助。

如果我没错,我必须为抽象类编写一个自定义绑定器,但我该怎么办呢?

此致

佐利

2 个答案:

答案 0 :(得分:1)

一种可能性是使用JSON.NET将内置JSON序列化程序替换为自定义格式化程序,如following blog post所示。

public class JsonNetFormatter : MediaTypeFormatter
{
    private JsonSerializerSettings _jsonSerializerSettings;

    public JsonNetFormatter(JsonSerializerSettings jsonSerializerSettings)
    {
        _jsonSerializerSettings = jsonSerializerSettings ?? new JsonSerializerSettings();

        // Fill out the mediatype and encoding we support
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
        Encoding = new UTF8Encoding(false, true);
    }

    protected override bool CanReadType(Type type)
    {
        if (type == typeof(IKeyValueModel))
        {
            return false;
        }

        return true;
    }

    protected override bool CanWriteType(Type type)
    {
        return true;
    }

    protected override Task<object> OnReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext)
    {
        // Create a serializer
        JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);

        // Create task reading the content
        return Task.Factory.StartNew(() =>
        {
            using (StreamReader streamReader = new StreamReader(stream, Encoding))
            {
                using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader))
                {
                    return serializer.Deserialize(jsonTextReader, type);
                }
            }
        });
    }

    protected override Task OnWriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext, TransportContext transportContext)
    {
        // Create a serializer
        JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);

        // Create task writing the serialized content
        return Task.Factory.StartNew(() =>
        {
            using (JsonTextWriter jsonTextWriter = new JsonTextWriter(new StreamWriter(stream, Encoding)) { CloseOutput = false })
            {
                serializer.Serialize(jsonTextWriter, value);
                jsonTextWriter.Flush();
            }
        });
    }
}

然后在Application_Start注册格式化程序时,您可以配置序列化程序以使用JSON中的类型信息:

var formatters = GlobalConfiguration.Configuration.Formatters;
formatters.Remove(formatters.XmlFormatter);
formatters.Remove(formatters.JsonFormatter);

var serializerSettings = new JsonSerializerSettings();
serializerSettings.TypeNameHandling = TypeNameHandling.Objects;
serializerSettings.Converters.Add(new IsoDateTimeConverter());
formatters.Add(new JsonNetFormatter(serializerSettings));

然后你可以发布以下JSON:

[
    { 
        "$type":"AppName.Models.TitleSlideItem, AppName",
        "Id":1,
        "Title":"some title" // this is a specific property of the TitleSlideItemclass
    },
    {
        "$type":"AppName.Models.ParagraphSlideItem, AppName",
        "Id":2,
        "Paragraph":"some paragraph" // this is a specific property of the ParagraphSlideItem class
    }
]

将在此操作中成功反序列化:

public HttpResponseMessage Post(IList<SlideItem> l)
{
    ...
}

答案 1 :(得分:1)

JsonFx创建自定义绑定器。例如,看看:

https://code.google.com/p/jsonfx/source/browse/trunk/JsonFx/JsonFx.MvcTemplate/Global.asax.cs

查看该文件中的RegisterBinders()函数和绑定器的源代码,或者只是安装JsonFx并使用他们的MVC模板创建项目,看看他们是如何做到的,或者只是使用他们的库,如果这对你有用。这就是我要做的。