使用TypeNameHandling对System.Drawing.Color进行JSON.NET序列化 [英] JSON.NET serialization of System.Drawing.Color with TypeNameHandling

查看:92
本文介绍了使用TypeNameHandling对System.Drawing.Color进行JSON.NET序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to serialize a Dictionary<string, object> that may contain System.Drawing.Color values or other types as values. I create a serializer with TypeNameHandling.Auto, and this works for most classes, but not Color.

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

Example code: (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.

As expected, instances of A or B in the dictionary have the needed $type metadata for reconstruction. But instances of Color do not. When this json is deserialized, dict["Rainbow"] is a System.String.

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

There are many ways I could work around this, but the preferred solution would be to figure out why the serializer is doing something seemingly incorrect with $type in this case.

推荐答案

问题是 TypeConverter ,Json.Net用来将类型转换为字符串值并返回.但是,由于输出值为字符串(不是复杂对象),因此Json.Net不会为其输出任何类型信息.如果将您的属性定义为object而不是强类型,这会在反序列化过程中引起问题:Json.Net将无法找到TypeConverter,因此它将无法将字符串值转换回Color.

The problem is that System.Drawing.Color has an associated TypeConverter, which Json.Net uses to convert the type to a string value and back. However, since the output value is a string (not an complex object), Json.Net does not output any type information for it. This causes an issue during deserialization if your property is defined as object instead of strongly typed: Json.Net won't be able to find the TypeConverter, so it will not be able to convert the string value back into a Color.

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

One way to work around the issue is to wrap the Color in another class which has a strongly-typed property for the color value.

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

然后,

Json.Net将为包装器类写出类型信息,这将允许对嵌套的Color结构进行正确的反序列化.这是一个往返演示:

Json.Net will then write out type information for the wrapper class, which will allow the nested Color struct to be deserialized correctly. Here is a round-trip demo:

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

这篇关于使用TypeNameHandling对System.Drawing.Color进行JSON.NET序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆