Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将TimeSpan值序列化和反序列化为Object类型的属性_C#_Json_Serialization_Json.net - Fatal编程技术网

C# 将TimeSpan值序列化和反序列化为Object类型的属性

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);

我有一个类,它有一个Object类型的字段,该字段可能包含一个TimeSpan对象

我正在序列化此和反序列化此:

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对象

两点:

  • 我不是在处理已经在其他地方序列化的字符串。我将反序列化的唯一字符串是我序列化的字符串
  • 字段必须是object类型-它可能包含字符串、日期时间或时间跨度。目前,这只是我遇到问题的时间跨度

  • 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)