Your GoogleSearchResults
type has fields and properties that have the same name. Try renaming your fields with leading underscores (anything that will disambiguate between the two).
[Update]
I've just realized why you weren't receiving results back... you have a missing line in your Deserialize
method. You were forgetting to assign the results to your obj
:
public static T Deserialise<T>(string json)
{
T obj = Activator.CreateInstance<T>();
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
obj = (T)serializer.ReadObject(ms); // <== Your missing line
return obj;
}
}
Also, just for reference, here is the Serialize
method :
public static string Serialize<T>(T obj)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, obj);
return Encoding.Default.GetString(ms.ToArray());
}
}
Now, the reason you're getting a StackOverflow is because of your Properties
.
Take for example this one :
[DataMember]
public string unescapedUrl
{
get { return unescapedUrl; } // <= this line is causing a Stack Overflow
set { this.unescapedUrl = value; }
}
Notice that in the getter
, you are returning the actual property (ie the property's getter is calling itself over and over again), and thus you are creating an infinite recursion.
Properties (in 2.0) should be defined like such :
string _unescapedUrl; // <= private field
[DataMember]
public string unescapedUrl
{
get { return _unescapedUrl; }
set { _unescapedUrl = value; }
}
You have a private field and then you return the value of that field in the getter, and set the value of that field in the setter.
Btw, if you're using the 3.5 Framework, you can just do this and avoid the backing fields, and let the compiler take care of that :
public string unescapedUrl { get; set;}
Your data class doesn't match the JSON object. Use this instead:
[DataContract]
public class GoogleSearchResults
{
[DataMember]
public ResponseData responseData { get; set; }
}
[DataContract]
public class ResponseData
{
[DataMember]
public IEnumerable<Results> results { get; set; }
}
[DataContract]
public class Results
{
[DataMember]
public string unescapedUrl { get; set; }
[DataMember]
public string url { get; set; }
[DataMember]
public string visibleUrl { get; set; }
[DataMember]
public string cacheUrl { get; set; }
[DataMember]
public string title { get; set; }
[DataMember]
public string titleNoFormatting { get; set; }
[DataMember]
public string content { get; set; }
}
Also, you don't have to instantiate the class to get its type for deserialization:
public static T Deserialise<T>(string json)
{
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
var serialiser = new DataContractJsonSerializer(typeof(T));
return (T)serialiser.ReadObject(ms);
}
}