我正在使用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了解详情。
答案 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;
}
}