【问题标题】:JSON.NET serialization of System.Drawing.Color with TypeNameHandling使用 TypeNameHandling 对 System.Drawing.Color 进行 JSON.NET 序列化
【发布时间】:2014-12-20 21:33:54
【问题描述】:

我想序列化一个可能包含System.Drawing.Color 值或其他类型作为值的Dictionary<string, object>。我用TypeNameHandling.Auto 创建了一个序列化程序,这适用于大多数类,但不适用于Color

示例代码:(DotNetFiddle:https://dotnetfiddle.net/UvphQO

public class Program
{
    class A { }
    class B { }

    public static void Main()
    {
        Dictionary<string, object> dict = new Dictionary<string, object>();
        dict["Foo"] = new A();
        dict["Bar"] = new B();
        dict["Baz"] = new object();
        dict["Rainbow"] = Color.FromArgb(20, 20, 20, 20);

        var ser = new JsonSerializer
        {
            TypeNameHandling = TypeNameHandling.Auto
        };
        var w = new JsonTextWriter(Console.Out)
        {
            Formatting = Formatting.Indented
        };
        ser.Serialize(w, dict);
    }
}

结果输出:

{
  "Foo": {
    "$type": "Program+A, mi1i2eqo"
  },
  "Bar": {
    "$type": "Program+B, mi1i2eqo"
  },
  "Baz": {},
  "Rainbow": "20, 20, 20, 20"
}

正如预期的那样,字典中AB 的实例具有重建所需的$type 元数据。但是Color 的实例没有。当这个 json 被反序列化时,dict["Rainbow"] 是一个System.String

有很多方法可以解决这个问题,但首选的解决方案是弄清楚为什么序列化程序在这种情况下使用$type 做一些看似不正确的事情。

【问题讨论】:

    标签: c# json.net


    【解决方案1】:

    问题在于System.Drawing.Color 有一个关联的TypeConverter,Json.Net 使用它来将类型转换为字符串值并返回。但是,由于输出值是字符串(不是复杂对象),Json.Net 不会为它输出任何类型信息。如果您的属性被定义为 object 而不是强类型,这会在反序列化期间导致问题:Json.Net 将无法找到 TypeConverter,因此它将无法将字符串值转换回 @ 987654327@.

    解决此问题的一种方法是将Color 包装在另一个类中,该类具有颜色值的强类型属性。

    class ColorHolder
    {
        public System.Drawing.Color Value { get; set; }
    }
    

    Json.Net 然后会写出包装类的类型信息,这将允许嵌套的Color 结构被正确反序列化。这是一个往返演示:

    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();
            dict["Rainbow"] = new ColorHolder { Value = Color.FromArgb(10, 20, 30, 40) };
    
            JsonSerializerSettings settings = new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Auto,
                Formatting = Formatting.Indented
            };
    
            string json = JsonConvert.SerializeObject(dict, settings);
            Console.WriteLine(json);
            Console.WriteLine();
    
            var d = JsonConvert.DeserializeObject<Dictionary<string, object>>(json, settings);
    
            ColorHolder holder = (ColorHolder)d["Rainbow"];
            Console.WriteLine("A=" + holder.Value.A);
            Console.WriteLine("R=" + holder.Value.R);
            Console.WriteLine("G=" + holder.Value.G);
            Console.WriteLine("B=" + holder.Value.B);
        }
    }
    

    输出:

    {
      "Rainbow": {
        "$type": "JsonTest.ColorHolder, JsonTest",
        "Value": "10, 20, 30, 40"
      }
    }
    
    A=10
    R=20
    G=30
    B=40
    

    【讨论】:

    • 看起来这也适用于任何带有TypeConverter 且可以转换为string 的类型。
    • 是的,肯定会的。
    【解决方案2】:

    您可以将 Color 序列化和反序列化为 Int32。 例如,我这样做:

            private Color _TextColor;
            public Color TextColor
            {
                get => _TextColor;
                set
                {
                    if (_TextColor != value)
                    {
                        _TextColor = value;
                        PropertyChangedCall("StyleProperty");
                    }
                }
            }
            public int TextColorValue
            {
                get => _TextColor.ToArgb();
                set
                {
                    if (_TextColor != Color.FromArgb(value))
                    {
                        _TextColor = Color.FromArgb(value);
                        PropertyChangedCall("StyleProperty");
                    }
                }
            }
    

    【讨论】:

      【解决方案3】:

      System.Drawing.Color 是一个结构,而不是 .NET 中的一个类。这听起来像是你的问题的答案。尝试用一个类来包装它,或者创建你自己的颜色类,它应该可以解决它。

      【讨论】:

      • 如果我修改我的原始示例并将class B 更改为struct B["Bar"] 仍然会得到适当的$type 元数据。所以不是这样。
      • 你为什么提到B?您说问题在于颜色类型未正确序列化(“彩虹”)。我说那是因为这是一个结构而不是一个类。请再读一遍我的回答。
      • 再清楚不过了。其他结构工作正常,所以它是一个结构这一事实并不是问题的原因。你不明白这个问题。
      猜你喜欢
      • 1970-01-01
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 2019-05-05
      • 1970-01-01
      相关资源
      最近更新 更多