C# DataContractJsonSerializer - 在 List<object> 中反序列化 DateTime
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9266435/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
DataContractJsonSerializer - Deserializing DateTime within List<object>
提问by Matthew Ruston
I'm having trouble using the System.Runtime.Serialization.Json.DataContractJsonSerializerclass to deserialize DateTime instances contained within a List<object>. I cannot seem to get DateTime to deserialize back into the original type. The DataContractJsonSerializeralways deserializes it into a string type with the format "/Date(1329159196126-0500)/". It'll serialize and deserialize fine if I run it through using a strongly typed List<DateTime>, however I am looking for way to get the serializer to identify and properly deserialize DateTimes when encountered within a simple list or array of object.
我在使用System.Runtime.Serialization.Json.DataContractJsonSerializer该类反序列化包含在List<object>. 我似乎无法让 DateTime 反序列化回原始类型。将DataContractJsonSerializer始终反序列化到一个字符串类型的格式"/Date(1329159196126-0500)/"。如果我使用强类型List<DateTime>的object.
Note that DateTimes are the only type besides primitives and strings that this list will ever contain. Here is the code snippet I'm using to test this.
请注意,DateTimes 是该列表将包含的除原语和字符串之外的唯一类型。这是我用来测试的代码片段。
var list = new List<object> { 27, "foo bar", 12.34m, true, DateTime.Now };
var serializer = new DataContractJsonSerializer(typeof (List<object>));
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, list);
ms.Position = 0;
var deserializedList = serializer.ReadObject(ms) as List<object>;
}
采纳答案by Mike Zboray
This seems like very strange behavior, my guess is that it stems from DateTime not being a type that is recongnized in JSON. However, you can roll your own IDataContractSurrogate to modify the serialization/deserialization process.
这似乎是非常奇怪的行为,我的猜测是它源于 DateTime 不是 JSON 中认可的类型。但是,您可以滚动自己的 IDataContractSurrogate 来修改序列化/反序列化过程。
To use this modify your sample code when you create the the serializer to this:
要在创建序列化程序时使用此修改示例代码:
var serializer = new DataContractJsonSerializer(typeof(List<object>), null, int.MaxValue, false, new DateTimeDataContractSurrogate(), true);
Then add this class:
然后添加这个类:
public class DateTimeDataContractSurrogate : IDataContractSurrogate
{
private static readonly Regex dateRegex = new Regex(@"/Date\((\d+)([-+])(\d+)\)/");
private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
// not used
return null;
}
public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
// not used
return null;
}
public Type GetDataContractType(Type type)
{
// not used
return type;
}
public object GetDeserializedObject(object obj, Type targetType)
{
// for debugging
//Console.WriteLine("GetDeserializedObject: obj = {0} ({1}), targetType = {2}", obj, obj.GetType(), targetType);
// only act on List<object> types
if (obj.GetType() == typeof(List<object>))
{
var objList = (List<object>)obj;
List<object> copyList = new List<object>(); // a list to copy values into. this will be the list returned.
foreach (var item in objList)
{
string s = item as string;
if (s != null)
{
// check if we match the DateTime format
Match match = dateRegex.Match(s);
if (match.Success)
{
// try to parse the string into a long. then create a datetime and convert to local time.
long msFromEpoch;
if (long.TryParse(match.Groups[1].Value, out msFromEpoch))
{
TimeSpan fromEpoch = TimeSpan.FromMilliseconds(msFromEpoch);
copyList.Add(TimeZoneInfo.ConvertTimeFromUtc(epoch.Add(fromEpoch), TimeZoneInfo.Local));
continue;
}
}
}
copyList.Add(item); // add unmodified
}
return copyList;
}
return obj;
}
public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes)
{
// not used
}
public object GetObjectToSerialize(object obj, Type targetType)
{
// for debugging
//Console.WriteLine("GetObjectToSerialize: obj = {0} ({1}), targetType = {2}", obj, obj.GetType(), targetType);
return obj;
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
// not used
return null;
}
public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{
// not used
return typeDeclaration;
}
}
回答by L.B
If DataContractJsonSerializerisn't a must, here is a solution using Json.Net.
如果DataContractJsonSerializer不是必须,这里有一个使用Json.Net的解决方案。
var list = new List<object> { 27, "foo bar", 12.34m, true, DateTime.Now };
string json = JsonConvert.SerializeObject(list);
var orgObj=JsonConvert.DeserializeObject<List<object>>(json);
This is the Json string
这是 Json 字符串
[27,"foo bar",12.34,true,"\/Date(1329161615596+0200)\/"]
and returned types are long,string,double,booland DateTime
和返回的类型是long, string, double,bool和DateTime
回答by brgerner
You could convert DateTime.Nowto a string before serialization and
convert it back to DateTimeafter deserialization.
您可以在序列化之前将DateTime.Now转换为字符串,并在反序列化之后
将其转换回DateTime。
Conversion to string by:
通过以下方式转换为字符串:
string dateAsString = Convert.ToString(DateTime.Now);
Conversion back to DateTime after deserialization:
反序列化后转换回 DateTime:
DateTime dateTime = Convert.ToDateTime(deserializedList[4]);
So the whole code would be like:
所以整个代码会是这样的:
string dateAsString = Convert.ToString(DateTime.Now);
var list = new object[] { 27, "foo bar", 12.34m, true, dateAsString };
var serializer = new DataContractJsonSerializer(typeof (List<object>));
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, list);
ms.Position = 0;
var deserializedList = serializer.ReadObject(ms) as List<object>;
DateTime dateTime = Convert.ToDateTime(deserializedList[4]);
}
回答by David Clarke
In the .NET Framework version 4.5 the DataContractJsonSerializerhas a constructor that accepts a DataContractJsonSerializerSettingsobject that can be used to set the DateTimeFormat:
在 .NET Framework 4.5 版中,DataContractJsonSerializer有一个构造函数接受一个DataContractJsonSerializerSettings对象,该对象可用于设置DateTimeFormat:
var ser = new DataContractJsonSerializer(typeof(CreateOmsEntryCommand),
new DataContractJsonSerializerSettings
{
DateTimeFormat = new DateTimeFormat("yyyy-MM-dd'T'HH:mm:ssZ")
});

