WCF DataContractJsonSerializer并将DateTime对象设置为UTC?

时间:2011-05-23 17:18:47

标签: c# asp.net wcf datetime serialization

是否有通用的方法来指示DataContractJsonSerializer将UTC用于日期?否则,我必须将.ToUniversalTime()添加到我的所有日​​期实例中。这可能吗?原因是日期值默认为DateTimeKind.Local并向JSON结果添加偏移量。让日期具有普遍性可以解决问题,但它可以在全球范围内完成吗?感谢。

1 个答案:

答案 0 :(得分:3)

在全局层面没有办法直接这样做 - 原始类型(如DateTime)不能“代理”。一种可能的解决方法是使用某种反射和代理来更改对象在序列化时的DateTime字段(或属性),如下例所示。

public class StackOverflow_6100587_751090
{
    public class MyType
    {
        public MyTypeWithDates d1;
        public MyTypeWithDates d2;
    }
    public class MyTypeWithDates
    {
        public DateTime Start;
        public DateTime End;
    }
    public class MySurrogate : IDataContractSurrogate
    {
        public object GetCustomDataToExport(Type clrType, Type dataContractType)
        {
            throw new NotImplementedException();
        }

        public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)
        {
            throw new NotImplementedException();
        }

        public Type GetDataContractType(Type type)
        {
            return type;
        }

        public object GetDeserializedObject(object obj, Type targetType)
        {
            return obj;
        }

        public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
        {
        }

        public object GetObjectToSerialize(object obj, Type targetType)
        {
            return ReplaceLocalDateWithUTC(obj);
        }

        public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
        {
            throw new NotImplementedException();
        }

        public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit)
        {
            throw new NotImplementedException();
        }

        private object ReplaceLocalDateWithUTC(object obj)
        {
            if (obj == null) return null;
            Type objType = obj.GetType();
            foreach (var field in objType.GetFields())
            {
                if (field.FieldType == typeof(DateTime))
                {
                    DateTime fieldValue = (DateTime)field.GetValue(obj);
                    if (fieldValue.Kind != DateTimeKind.Utc)
                    {
                        field.SetValue(obj, fieldValue.ToUniversalTime());
                    }
                }
            }

            return obj;
        }
    }
    public static void Test()
    {
        MemoryStream ms = new MemoryStream();
        DataContractJsonSerializer dcjs = new DataContractJsonSerializer(typeof(MyType), null, int.MaxValue, true, new MySurrogate(), false);
        MyType t = new MyType
        {
            d1 = new MyTypeWithDates { Start = DateTime.Now, End = DateTime.Now.AddMinutes(1) },
            d2 = new MyTypeWithDates { Start = DateTime.Now.AddHours(1), End = DateTime.Now.AddHours(2) },
        };
        dcjs.WriteObject(ms, t);
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
    }
}