Почему я использую атрибут KnownType неправильно? - PullRequest
4 голосов
/ 19 ноября 2009

Я пытаюсь десериализовать ответ json от API Google, поэтому я решил определить пару классов, чтобы помочь с этим:

[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; }
}

Ответ, который я получаю после выполнения запроса:

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

и используйте этот код для десериализации:

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

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

            stream.Close();
        }

Но я получаю исключение о том, что "Не удается создать абстрактный класс". Разве он не должен знать о классе DetectionResult и правильно десериализовать его?

Ответы [ 4 ]

11 голосов
/ 19 ноября 2009

В ваших данных ответа нет никакого способа вывести конкретный тип. Тип для десериализации не указан в ответе.

Из MSDN:

Для сохранения идентичности типов при сериализации сложных типов в JSON «подсказка типа» может быть добавлена, и десериализатор распознает подсказку и действует соответственно. «Тип подсказка» представляет собой пару ключ / значение JSON с ключевое имя «__type» (два подчеркивания, за которыми следует слово «type»). Значение представляет собой строку JSON в форме «DataContractName: DataContractNamespace» (что-либо до первого двоеточие это имя). Используя предыдущий пример, «Круг» может быть сериализовано следующим образом.

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

См. Раздел, связанный с полиморфизмом.

1 голос
/ 19 ноября 2009

В этом примере кода необходимо, чтобы [KnownType (typeof (DetectionResult))] был атрибутом ResponseData, а не RequestResult.

Я не знаю, достаточно ли этого для решения вашей проблемы

1 голос
/ 19 ноября 2009

Вы пытались поместить атрибут KnownType в ResponseData вместо RequestResult?

0 голосов
/ 19 ноября 2009

Из моего опыта работы с DataContractSerializer и XmlSerializer, когда неожиданный тип встречается в процессе сериализации, эти сериализаторы выдают исключение; они не просто делают все возможное. Возможно, DataContractJsonSerializer вообще не поддерживает KnownTypes.

...