views:

499

answers:

4

I am trying to deserialize a json response from a google api, so i thought i would define a couple classes to help with it:

[DataContract]
public class DetectionResult:ResponseData
{
    [DataMember(Name="language")]
    public string Language
    { get; set; }

    [DataMember(Name="isReliable")]
    public bool IsReliable
    { get; set; }

    [DataMember(Name="confidence")]
    public double Confidence
    {get;set;}
}

[DataContract]
public abstract class ResponseData
{

    [DataMember(Name = "error")]
    public TranslationError Error
    { get; set; }

}

[DataContract]
public class TranslationError
{
    [DataMember(Name="code")]
    public int Code
    { get; set; }

    [DataMember(Name="message" )]
    public int Message
    { get; set; }
}


[DataContract]
[KnownType(typeof(DetectionResult))]
public class RequestResult
{
    [DataMember(Name="responseStatus")]
    public int ResponseStatus
    { get; set; }

    [DataMember(Name="responseDetails")]
    public string ResponseDetails
    { get; set; }

    [DataMember(Name = "responseData")]
    public ResponseData Response
    { get; set; }
}

The response I get after making the request is:

{"responseData": {"language":"en","isReliable":false,"confidence":0.114892714}, "responseDetails": null, "responseStatus": 200}

and use this code to deserialize it:

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  using (Stream stream = response.GetResponseStream())
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(RequestResult));

            RequestResult result = (RequestResult)serializer.ReadObject(stream);                

            stream.Close();
        }

But am getting an exception stating "Cannot create an abstract class". Shouldnt it know about the DetectionResult class and properly deserialize it?

+1  A: 

Have you tried putting the KnownType attribute on ResponseData instead of RequestResult?

Neil Whitaker
+1  A: 

In that code sample you need [KnownType(typeof(DetectionResult))] to be an attribute of ResponseData rather than RequestResult.

I don't know if that's sufficient to resolve your problem

Murph
Ive tried that as well, and i get the same exception.
Mike_G
+4  A: 

In your response data there is no way to infer a concrete type. The type to deserialize is not specified in the response.

From MSDN: "To preserve type identity, when serializing complex types to JSON a "type hint" can be added, and the deserializer recognizes the hint and acts appropriately. The "type hint" is a JSON key/value pair with the key name of "__type" (two underscores followed by the word "type"). The value is a JSON string of the form "DataContractName:DataContractNamespace" (anything up to the first colon is the name). Using the earlier example, "Circle" can be serialized as follows."

http://msdn.microsoft.com/en-us/library/bb412170.aspx

See the section related to polymorphism.

Alex
Awesome link! Thank you so much for finding it.
Mike_G
A: 

From my experience working with the DataContractSerializer and the XmlSerializer, when an unexpected type is met during serialization process, those serializers throw an exception; they don't simply do the best they can. Maybe the DataContractJsonSerializer does not support KnownTypes at all.

Sly