I have a PhoneNumber class that stores a normalized string, and I've define开发者_Go百科d implicit operators for string <-> Phone to simplify treatment of the PhoneNumber as a string. I've also overridden the ToString() method to always return the cleaned version of the number (no hyphens or parentheses or spaces). In any views where I display the number, I explicitly call phone.Format().
The problem here is serializing an entity that has a PhoneNumber to JSON; JavaScriptSerializer serializes it as [object Object]
.
I want to serialize it as a string in (555)555-5555 format.
I've looked at writing a custom JavaScriptConverter, but JavaScriptConverter.Serialize() method returns a dictionary of name-value pairs. I do not want PhoneNumber to be treated as an object with fields, I want to simply serialize it as a string.
It's worth considering the JSON you want.
Assuming you have this class
class Person
{
public string Name { get; set; }
public PhoneNumber HomePhone { get; set; }
}
You want this serialized to JSON, like this
{ "Name":"Joe", "HomePhone": "555-555-555" }
But you are getting JSON, something like this
{ "Name":"Joe","HomePhone": {"Number": "555-555-555"} }
--
To see why this is so, consider that the property Number of Person is an object. JSON is going to expect at least a {} to wrap the object - or more to the point, a set of name/values within the {}.
If you really, really want the former JSON syntax you need to register a custom converter for the Person object so that you can convince it to serialize and deserialze as a string. (see code example below).
However, I'd recommend that you just accept that because PhoneNumber is an object it correspond to a name/value dictionary when serialized into JSON and accept that the JSON is going to look a little less 'clean' than you might ideally want.
FWIW here's a code example that achieves your original aim (not the recommended approach)..
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));
}
}
I know this is old, but when searching I came across this while looking for the answer to the OP's question. The answer presented there is to create a named type, that inherits from URI and implements the IDictionary interface. When it is then serialized, .Net recognizes the URI inheritence and outputs a string instead of an object collection. This leaves you with a large nearly worthless class just needed for the purposes of passing the Dictionary out of the overridden serialization method.
If someone else has a way to do this without the extra class and useless methods that would be great. Otherwise here is a 'way' to do it.
精彩评论