JSON.NET System.Drawing.Color with TypeNameHandling 的序列化

本文关键字:TypeNameHandling 序列化 with Color NET System Drawing JSON | 更新日期: 2023-09-27 18:34:46

我想序列化可能包含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执行看似不正确的操作。

JSON.NET System.Drawing.Color with TypeNameHandling 的序列化

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

解决此问题的一种方法是将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

可以将 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");
                }
            }
        }

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

相关文章:
  • 没有找到相关文章