Web API:无法序列化内容类型

时间:2015-11-06 03:40:54

标签: json asp.net-web-api json.net json-deserialization jsonserializer

我正在使用ASP.NET MVC 5 Web Api。

我现在有很多api的应用程序。 最近我实现了自定义JsonConverter,它将根据时区转换日期。

public class CustomInfoConverter : JsonConverter
{

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(CustomType);
    }
    public override bool CanRead
    {
        get
        {
            return false;
        }
    }
    public override bool CanWrite
    {
        get
        {
            return true;
        }
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var customType = (CustomType)value;
        if (customType == null || null== customType.TimeZone) return;
        //DateTime currentDateTime = customType.Date??DateTime.Now;
        DateTime currentDateTime = DateTime.SpecifyKind(customType.Date ?? DateTime.Now, DateTimeKind.Unspecified);

        DateTime userDateTime = TimeZoneInfo.ConvertTimeFromUtc(currentDateTime, customType.TimeZone);
        customType.Date = userDateTime;
        JsonSerializer innerSerializer = new JsonSerializer();
        foreach (var converter in serializer.Converters.Where(c => !(c is CustomInfoConverter)))
        {
            innerSerializer.Converters.Add(converter);
        }
        innerSerializer.Serialize(writer, customType);


    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }


}

实现这个自定义JsonConverter之后,所有api都在工作,除了一个api,它抛出异常

  

{"消息":"发生了错误。"," ExceptionMessage":" The   ' ObjectContent`1'类型无法序列化响应正文   内容类型' application / json;   字符集= UTF-8'"" ExceptionType":" System.InvalidOperationException""堆栈跟踪":空,"的InnerException& #34; {"消息":"安   错误已经发生。"," ExceptionMessage":" Token PropertyName in state   属性将导致无效的JSON对象。路径   ' Data.Forms [0]'"" ExceptionType":" Newtonsoft.Json.JsonWriterException""堆栈跟踪" :"   在Newtonsoft.Json.JsonWriter.AutoComplete(JsonToken   tokenBeingWritten)\ r \ n at   Newtonsoft.Json.JsonWriter.InternalWritePropertyName(String name)\ r \ n   at Newtonsoft.Json.JsonTextWriter.WritePropertyName(String name,   布尔转义)\ r \ n at   Newtonsoft.Json.Serialization.JsonProperty.WritePropertyName(JsonWriter   作家)\ r \ n at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter   writer,Object value,JsonObjectContract契约,JsonProperty   成员,JsonContainerContract collectionContract,JsonProperty   containerProperty)\ r \ n at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter   writer,Object value,JsonContract valueContract,JsonProperty成员,   JsonContainerContract containerContract,JsonProperty   containerProperty)\ r \ n at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter   writer,IEnumerable值,JsonArrayContract契约,JsonProperty   成员,JsonContainerContract collectionContract,JsonProperty   containerProperty)\ r \ n at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter   writer,Object value,JsonContract valueContract,JsonProperty成员,   JsonContainerContract containerContract,JsonProperty   containerProperty)\ r \ n at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter   writer,Object value,JsonObjectContract契约,JsonProperty   成员,JsonContainerContract collectionContract,JsonProperty   containerProperty)\ r \ n at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter   writer,Object value,JsonContract valueContract,JsonProperty成员,   JsonContainerContract containerContract,JsonProperty   containerProperty)\ r \ n at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter   writer,Object value,JsonObjectContract契约,JsonProperty   成员,JsonContainerContract collectionContract,JsonProperty   containerProperty)\ r \ n at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter   writer,Object value,JsonContract valueContract,JsonProperty成员,   JsonContainerContract containerContract,JsonProperty   containerProperty)\ r \ n at   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter   jsonWriter,Object value,Type objectType)\ r \ n at   Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter   jsonWriter,Object value,Type objectType)\ r \ n at   Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter,Object   价值)\ r \ n at   System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(类型   type,Object value,Stream writeStream,Encoding   有效编码)\ r \ n at   System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(类型   type,Object value,Stream writeStream,Encoding   有效编码)\ r \ n at   System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(类型   type,Object value,Stream writeStream,HttpContent content)\ r \ n at   System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(类型   type,Object value,Stream writeStream,HttpContent内容,   TransportContext transportContext,CancellationToken   cancellationToken)\ r \ n ---从前一个位置开始的堆栈跟踪结束   抛出异常的地方--- \ r \ n at   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)\ r \ n at   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)\ r \ n at   System.Runtime.CompilerServices.TaskAwaiter.GetResult()\ r \ n at   System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext()"}}

您可以参考此link了解详情。

1 个答案:

答案 0 :(得分:1)

问题似乎是,在某些情况下,您从WriteJson()返回而没有写任何内容,特别是在customType.TimeZone == null时:

    var customType = (CustomType)value;
    if (customType == null || null== customType.TimeZone) return;

这样做会导致JSON对象无效,因为调用者已经编写了 name 属性,导致:

{
    "customType":
}

尝试执行此操作会导致您看到异常。

相反,您需要阻止属性本身被序列化。但是,在转换器中这是不可能的,它需要在包含类型中完成。

为避免序列化具有空值的属性,您应在serializer settings中或在属性本身上设置NullValueHandling = NullValueHandling.Ignore

public class ContainerClass
{
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public CustomType CustomType { get; set; }
}

要防止在TimeZone属性为空时序列化您的属性,您应该使用conditional property serialization方法向包含类型添加ShouldSerializeXXX()方法,其中XXX与您的属性完全匹配财产名称:

public class ContainerClass
{
    public CustomType CustomType { get; set; }

    public bool ShouldSerializeCustomType()
    {
        return CustomType != null && CustomType.TimeZone != null;
    }
}