Recently, I've realised that I have not implemented the deserialization methods for the OpenSocial API for pesta. I found out while trying to deserialize Google Friend Connect data. Oops. I guess my memory is not as good as it used to be.
I found out that the DataContractSerializer is not effective when some fields are missing in the JSON string. So I finally implemented the Deserialize method for a custom JavaScriptConverter for the JavaScriptSerializer. I couldn't find a good example from the net. But I didn't spend too long searching so I could have missed out.
Basically, it uses reflection to determine the field type and to set the value of the field. This is done recursively from the dictionary of field names and values. Known issue, it currently does not handle the case where the field type is a dictionary. Will do this later when needed.
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
return ConvertToObject(dictionary, type);
}
public object ConvertToObject(IDictionary<string, object> dictionary, Type type)
{
var obj = Activator.CreateInstance(type);
foreach (var entry in dictionary)
{
var fieldType = type.GetProperty(entry.Key).PropertyType;
var valueType = entry.Value.GetType();
if (typeof(IDictionary).IsAssignableFrom(valueType))
{
ConvertToObject((IDictionary<string, object>)entry.Value, fieldType);
}
else
{
if (typeof(IList).IsAssignableFrom(fieldType))
{
Type argType = fieldType.GetGenericArguments()[0];
var listObj = Activator.CreateInstance(fieldType);
foreach (var val in (IList)entry.Value)
{
((IList)listObj).Add(ConvertToObject((IDictionary<string, object>)val, argType));
}
}
else
{
type.GetProperty(entry.Key).SetValue(obj, entry.Value, null);
}
}
}
return obj;
}
To use the converter, you just need to specify it when instantiating the JavaScriptSerializer object like so
public override T ConvertToObject<T>(String json)
{
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new JavaScriptConverter[] { new DataContractJSConverter() });
return serializer.Deserialize<T>(json);
}
The entire custom JavaScriptConverter class is viewable here, http://code.google.com/p/pesta/source/browse/trunk/pesta/pesta/Engine/protocol/conversion/DataContractJSConverter.cs.