Web API: 无法序列化内容类型的响应正文
Web API: Failed to serialize the response body for content type
我正在使用 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,它抛出以下异常
{"Message":"An error has occurred.","ExceptionMessage":"The
'ObjectContent`1' type failed to serialize the response body for
content type 'application/json;
charset=utf-8'.","ExceptionType":"System.InvalidOperationException","StackTrace":null,"InnerException":{"Message":"An
error has occurred.","ExceptionMessage":"Token PropertyName in state
Property would result in an invalid JSON object. Path
'Data.Forms[0]'.","ExceptionType":"Newtonsoft.Json.JsonWriterException","StackTrace":"
at Newtonsoft.Json.JsonWriter.AutoComplete(JsonToken
tokenBeingWritten)\r\n at
Newtonsoft.Json.JsonWriter.InternalWritePropertyName(String name)\r\n
at Newtonsoft.Json.JsonTextWriter.WritePropertyName(String name,
Boolean escape)\r\n at
Newtonsoft.Json.Serialization.JsonProperty.WritePropertyName(JsonWriter
writer)\r\n at
Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter
writer, Object value, JsonObjectContract contract, JsonProperty
member, JsonContainerContract collectionContract, JsonProperty
containerProperty)\r\n at
Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter
writer, Object value, JsonContract valueContract, JsonProperty member,
JsonContainerContract containerContract, JsonProperty
containerProperty)\r\n at
Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter
writer, IEnumerable values, JsonArrayContract contract, JsonProperty
member, JsonContainerContract collectionContract, JsonProperty
containerProperty)\r\n at
Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter
writer, Object value, JsonContract valueContract, JsonProperty member,
JsonContainerContract containerContract, JsonProperty
containerProperty)\r\n at
Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter
writer, Object value, JsonObjectContract contract, JsonProperty
member, JsonContainerContract collectionContract, JsonProperty
containerProperty)\r\n at
Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter
writer, Object value, JsonContract valueContract, JsonProperty member,
JsonContainerContract containerContract, JsonProperty
containerProperty)\r\n at
Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter
writer, Object value, JsonObjectContract contract, JsonProperty
member, JsonContainerContract collectionContract, JsonProperty
containerProperty)\r\n at
Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter
writer, Object value, JsonContract valueContract, JsonProperty member,
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
value)\r\n at
System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type
type, Object value, Stream writeStream, Encoding
effectiveEncoding)\r\n at
System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type
type, Object value, Stream writeStream, Encoding
effectiveEncoding)\r\n at
System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type
type, Object value, Stream writeStream, HttpContent content)\r\n at
System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type
type, Object value, Stream writeStream, HttpContent content,
TransportContext transportContext, CancellationToken
cancellationToken)\r\n--- End of stack trace from previous location
where exception was thrown ---\r\n at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task)\r\n at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task)\r\n at
System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n at
System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext()"}}
您可以参考这篇了解更多详情。
问题似乎是,在某些情况下,您从 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
属性 为 null 时序列化您的 属性,您应该通过向包含类型添加 ShouldSerializeXXX()
方法来使用 conditional property serialization ,其中 XXX
与您的 属性 姓名完全匹配:
public class ContainerClass
{
public CustomType CustomType { get; set; }
public bool ShouldSerializeCustomType()
{
return CustomType != null && CustomType.TimeZone != null;
}
}
我正在使用 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,它抛出以下异常
{"Message":"An error has occurred.","ExceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.","ExceptionType":"System.InvalidOperationException","StackTrace":null,"InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Token PropertyName in state Property would result in an invalid JSON object. Path 'Data.Forms[0]'.","ExceptionType":"Newtonsoft.Json.JsonWriterException","StackTrace":" at Newtonsoft.Json.JsonWriter.AutoComplete(JsonToken tokenBeingWritten)\r\n at Newtonsoft.Json.JsonWriter.InternalWritePropertyName(String name)\r\n at Newtonsoft.Json.JsonTextWriter.WritePropertyName(String name, Boolean escape)\r\n at Newtonsoft.Json.Serialization.JsonProperty.WritePropertyName(JsonWriter writer)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, 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 value)\r\n at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n at System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)\r\n at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n at System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext()"}}
您可以参考这篇
问题似乎是,在某些情况下,您从 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
属性 为 null 时序列化您的 属性,您应该通过向包含类型添加 ShouldSerializeXXX()
方法来使用 conditional property serialization ,其中 XXX
与您的 属性 姓名完全匹配:
public class ContainerClass
{
public CustomType CustomType { get; set; }
public bool ShouldSerializeCustomType()
{
return CustomType != null && CustomType.TimeZone != null;
}
}