Managing the JSON Serialization Format of a Custom Type in .NET

I have a PhoneNumber class that stores a normalized string, and I have defined implicit operators for string ↔ Phone to make it easier to process PhoneNumber as a string. I also overridden the ToString () method to always return a cleared version of the number (without a hyphen or parentheses or spaces). In any views where I show the number, I explicitly call phone.Format ().

The problem here is serializing an object that has a phone number for JSON; JavaScriptSerializer serializes it as [object Object].

I want to serialize it as a string in the format (555) 555-5555.

I looked at creating a custom JavaScriptConverter, but the JavaScriptConverter.Serialize () method returns a dictionary of name-value pairs. I do not want PhoneNumber to be treated as an object with fields, I just want to serialize it as a string.

+3
source share
2 answers

It is worth considering the JSON you want.

Assuming you have this class

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

Do you want this serialized json like this

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

But you get JSON, something like this

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

-

To understand why this is so, consider the Number of Person property to be an object . JSON expects at least {} to wrap an object - or more to the point, a set of names / values ​​inside {}.

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 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));
    }
}
+1

, , this, OP. , URI IDictionary. ,.Net URI . , .

- , . "" .

0

Source: https://habr.com/ru/post/1740244/


All Articles