C# 将TimeSpan值序列化和反序列化为Object类型的属性
我有一个类,它有一个Object类型的字段,该字段可能包含一个TimeSpan对象 我正在序列化此和反序列化此:C# 将TimeSpan值序列化和反序列化为Object类型的属性,c#,json,serialization,json.net,C#,Json,Serialization,Json.net,我有一个类,它有一个Object类型的字段,该字段可能包含一个TimeSpan对象 我正在序列化此和反序列化此: public class MyObject { public object myTimeSpan { get; set; } } ... var myObject = new MyObject { myTimeSpan = TimeSpan.FromDays(2) }; var json = JsonConvert.SerializeObject(myObject);
public class MyObject
{
public object myTimeSpan { get; set; }
}
...
var myObject = new MyObject { myTimeSpan = TimeSpan.FromDays(2) };
var json = JsonConvert.SerializeObject(myObject);
...
var duplicateObject = JsonConvert.DeserializeObject<MyObject>(json);
公共类MyObject
{
公共对象myTimeSpan{get;set;}
}
...
var myObject=new myObject{myTimeSpan=TimeSpan.FromDays(2)};
var json=JsonConvert.SerializeObject(myObject);
...
var duplicateObject=JsonConvert.DeserializeObject(json);
当我这样做时,duplicateObject.myTimeSpan包含字符串“2:00:00”
如何将其反序列化为TimeSpan对象
两点:
Json.Net有一个
TypeNameHandling
设置,用于处理未知类型,以便可以正确地反序列化它们。启用此设置时,会导致Json.Net在Json中插入特殊的$type
属性,然后在反序列化时用作提示。不幸的是,此设置似乎不适用于“简单”类型,例如TimeSpan
,因为它们的值被序列化为字符串而不是对象
为了解决这个问题,我建议制作一个使用相同思想的自定义JsonConverter
。转换器不会直接输出对象的字符串值,而是输出具有两个属性的子对象表示:type
和value
。子对象的type
属性将包含对象的程序集限定类型名称,而value
属性将包含实际序列化的值。反序列化时,转换器将查找type
属性,以了解要从value属性实例化的对象类型。这种方法的优点是不必向模型类添加任何附加属性或逻辑
下面是它在代码中的外观:
class UnknownObjectConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JObject jo = new JObject();
jo["type"] = value.GetType().AssemblyQualifiedName;
jo["value"] = JToken.FromObject(value, serializer);
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
Type type = Type.GetType(jo["type"].ToString(), throwOnError: true);
return jo["value"].ToObject(type, serializer);
}
}
要使用转换器,只需使用[JsonConverter]
属性修饰类中需要特殊处理的任何对象
属性,如下所示:
public class MyObject
{
[JsonConverter(typeof(UnknownObjectConverter))]
public object MyValue { get; set; }
}
下面是一个往返演示,它展示了如何为几种不同的类型工作
class Program
{
static void Main(string[] args)
{
List<MyObject> list = new List<MyObject>
{
new MyObject { MyValue = TimeSpan.FromDays(2) },
new MyObject { MyValue = "foo" },
new MyObject { MyValue = new DateTime(2014, 12, 20, 17, 06, 44) },
new MyObject { MyValue = new Tuple<int, bool>(23, true) }
};
string json = JsonConvert.SerializeObject(list, Formatting.Indented);
Console.WriteLine(json);
Console.WriteLine();
list = JsonConvert.DeserializeObject<List<MyObject>>(json);
foreach (MyObject obj in list)
{
Console.WriteLine(obj.MyValue.GetType().Name + ": " + obj.MyValue.ToString());
}
}
}
您的代码似乎不完整。您实际序列化的“selectionCriteria”是什么?我猜您的意思是
var json=JsonConvert.SerializeObject(myObject)代码>。如果我这样做,我会得到JSON{“myTimeSpan”:“2.00:00:00”}
,并且复制的对象有2天的时间跨度。对不起。剪切粘贴错误-已修复。当基础字段的类型为object时,我没有得到TimeSpan对象。您可能需要实现一个自定义的JsonConverter
,它可以尝试将TimeSpan
的字符串表示形式解析回实际的TimeSpan
对象。在ReadJson下,首先需要检查空类型,否则序列化空类型时会出现异常。if(reader.TokenType==JsonToken.Null)返回Null;很难找到TimeSpan序列化结果的示例。我注意到发送一个int 4会产生四天的时间跨度,但我不能像0.25那样通过双精度测试。幸运的是,我在你的回答中注意到了格式“d.hh:mm:ss”。谢谢和+1。
[
{
"MyValue": {
"type": "System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"value": "2.00:00:00"
}
},
{
"MyValue": {
"type": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"value": "foo"
}
},
{
"MyValue": {
"type": "System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"value": "2014-12-20T17:06:44"
}
},
{
"MyValue": {
"type": "System.Tuple`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"value": {
"Item1": 23,
"Item2": true
}
}
}
]
TimeSpan: 2.00:00:00
String: foo
DateTime: 12/20/2014 5:06:44 PM
Tuple`2: (23, True)