Teu*_*n D 51 c# wcf serialization datetime json
我遇到了WCF REST服务的问题.我尝试返回的wire对象具有未设置的某些属性,导致DateTime.MinValue为DateTime类型的属性.该服务返回一个空文档(HTTP状态为200 ???).当我尝试自己调用JSON序列化时,抛出的异常是:
SerializationException:转换为UTC时,大于DateTime.MaxValue或小于DateTime.MinValue的DateTime值无法序列化为JSON.
这可以通过在控制台应用程序中运行以下代码来重现:
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(DateTime));
MemoryStream m = new MemoryStream();
DateTime dt = DateTime.MinValue;
// throws SerializationException in my timezone
ser.WriteObject(m, dt);
string json = Encoding.ASCII.GetString(m.GetBuffer());
Console.WriteLine(json);
Run Code Online (Sandbox Code Playgroud)
为什么会这样?我认为这与我的时区(GMT + 1)有关.由于DateTime.MinValue是默认值(DateTime),我希望这可以没有问题地序列化.
有关如何使我的REST服务行为的任何提示?我不想改变我的DataContract.
Nic*_*nko 68
最主要的问题是DateTime.MinValue有DateTimeKind.Unspecified样.它被定义为:
MinValue = new DateTime(0L, DateTimeKind.Unspecified);
Run Code Online (Sandbox Code Playgroud)
但这不是一个真正的问题,这个定义会在序列化过程中导致问题.JSON DateTime序列化通过以下方式完成:
System.Runtime.Serialization.Json.JsonWriterDelegator.WriteDateTime(DateTime value)
Run Code Online (Sandbox Code Playgroud)
不幸的是它被定义为:
...
if (value.Kind != DateTimeKind.Utc)
{
long num = value.Ticks - TimeZone.CurrentTimeZone.GetUtcOffset(value).Ticks;
if ((num > DateTime.MaxValue.Ticks) || (num < DateTime.MinValue.Ticks))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString("JsonDateTimeOutOfRange"), new ArgumentOutOfRangeException("value")));
}
}
...
Run Code Online (Sandbox Code Playgroud)
所以它没有考虑到Unspecified并将其视为Local.要避免这种情况,您可以定义自己的常量:
MinValueUtc = new DateTime(0L, DateTimeKind.Utc);
Run Code Online (Sandbox Code Playgroud)
要么
MinValueUtc = DateTime.MinValue.ToUniversalTime();
Run Code Online (Sandbox Code Playgroud)
当然看起来很奇怪,但它有所帮助.
小智 13
尝试在任何DateTime成员上添加此项
[DataMember(IsRequired = false, EmitDefaultValue = false)]
Run Code Online (Sandbox Code Playgroud)
大多数这些错误发生是因为默认值datetime是DateTime.MinValue1年,而JSON序列化是从1970年开始.
如果您的时区是GMT + 1,那么DateTime.MinValue您所在时区的UTC值将小于一小时DateTime.MinValue.
小智 5
使用此构造函数:
public DataContractJsonSerializer(Type type, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, IDataContractSurrogate dataContractSurrogate, bool alwaysEmitTypeInformation)
Run Code Online (Sandbox Code Playgroud)
示例代码:
DataContractJsonSerializer serializer = new DataContractJsonSerializer(o.GetType(), null, int.MaxValue, false, new DateTimeSurrogate(), false);
public class DateTimeSurrogate : IDataContractSurrogate
{
#region IDataContractSurrogate ??
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
return null;
}
public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
return null;
}
public Type GetDataContractType(Type type)
{
return type;
}
public object GetDeserializedObject(object obj, Type targetType)
{
return obj;
}
public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes)
{
}
public object GetObjectToSerialize(object obj, Type targetType)
{
if (obj.GetType() == typeof(DateTime))
{
DateTime dt = (DateTime)obj;
if (dt == DateTime.MinValue)
{
dt = DateTime.MinValue.ToUniversalTime();
return dt;
}
return dt;
}
if (obj == null)
{
return null;
}
var q = from p in obj.GetType().GetProperties()
where (p.PropertyType == typeof(DateTime)) && (DateTime)p.GetValue(obj, null) == DateTime.MinValue
select p;
q.ToList().ForEach(p =>
{
p.SetValue(obj, DateTime.MinValue.ToUniversalTime(), null);
});
return obj;
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
return null;
}
public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{
return typeDeclaration;
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
28014 次 |
| 最近记录: |