3

我有一个存储规范化字符串的 PhoneNumber 类,并且我为字符串 <-> Phone 定义了隐式运算符,以简化将 PhoneNumber 视为字符串的处理。我还重写了 ToString() 方法以始终返回数字的清理版本(没有连字符、括号或空格)。在我显示号码的任何视图中,我都会显式调用 phone.Format()。

这里的问题是将具有PhoneNumber 的实体序列化为JSON;JavaScriptSerializer 将其序列化为[object Object].

我想将它序列化为 (555)555-5555 格式的字符串。

我看过编写自定义 JavaScriptConverter,但 JavaScriptConverter.Serialize() 方法返回名称-值对的字典。我希望 PhoneNumber 被视为具有字段的对象,我只想将其序列化为字符串。

4

2 回答 2

1

值得考虑您想要的 JSON。

假设你有这门课

class Person
{
    public string Name { get; set; }
    public PhoneNumber HomePhone { get; set; }
}

您希望将其序列化为 JSON,如下所示

{ "Name":"Joe", "HomePhone": "555-555-555" }

但是你得到的是 JSON,像这样

{ "Name":"Joe","HomePhone": {"Number": "555-555-555"} }

--

要了解为什么会这样,请考虑属性Number of Person是一个object。JSON 至少需要一个{}来包装对象,或者更确切地说,是 {} 中的一组名称/值。

如果您真的非常想要以前的 JSON 语法,您需要为Person对象注册一个自定义转换器,以便您可以说服它将序列化和反序列化为字符串。(见下面的代码示例)。

但是,我建议您接受这一点,因为 PhoneNumber 是一个对象,它在序列化为 JSON 时对应于名称/值字典,并接受 JSON 看起来比您理想中的“干净”少一点。

FWIW 这是一个实现您最初目标的代码示例(不是推荐的方法)..

class Person
{
    public string Name { get; set; }
    public PhoneNumber HomeNumber { get; set; }
}

struct PhoneNumber
{
    private string _number;
    public PhoneNumber(string number)
    {
        _number = number;
    }

    public override string ToString()
    {
        return _number;
    }
}

class PersonConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { yield return typeof(Person); }
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        Person person = obj as Person;
        if (person != null)
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();
            dict["Name"] = person.Name;
            dict["HomeNumber"] = person.HomeNumber.ToString();
            return dict;
        }
        return new Dictionary<string, object>();
    }

    public override object Deserialize(IDictionary<string, object> dict, Type type, JavaScriptSerializer serializer)
    {
        if (dict == null)
            throw new ArgumentNullException("dict");

        if (type == typeof(Person))
        {
            // Deserialize the Person's single property.
            string name = (string)dict["Name"];
            string homeNumber = (string)dict["HomeNumber"];

            // Create the instance to deserialize into.
            Person person = new Person()
            {
                Name = name,
                HomeNumber = new PhoneNumber(homeNumber)
            };
            return person;
        }
        return null;
    }
}

class Program
{
    static void Main(string[] args)
    {
        PhoneNumber number = new PhoneNumber("555 555");
        Person joe = new Person() { Name = "Joe", HomeNumber = number };

        JavaScriptSerializer serializer = new JavaScriptSerializer();
        serializer.RegisterConverters(new JavaScriptConverter[] { new PersonConverter() });
        Console.Out.WriteLine(serializer.Serialize(joe));
    }
}
于 2010-04-08T02:11:36.167 回答
0

我知道这很旧,但是在搜索时我在寻找 OP 问题的答案时遇到了这个问题。那里给出的答案是创建一个命名类型,它继承自 URI 并实现 IDictionary 接口。当它被序列化时,.Net 识别 URI 继承并输出一个字符串而不是一个对象集合。这为您留下了一个几乎毫无价值的大类,仅用于将 Dictionary 传递出覆盖的序列化方法。

如果其他人有办法做到这一点,而无需额外的类和无用的方法,那就太好了。否则,这是一种“方法”。

于 2018-02-20T18:24:54.137 回答