Проблема десериализации DataContractJsonSerializer

Мне нужно де-сериализовать массив Json, который указан ниже ....

[
    {
        "GeoType": 1,
        "ID": "2650f7d2-7a5e-4b63-856c-07600fa2a854",
        "Name": "Afghanistan",
        "CapitalCity": null,
        "CountryBoundaries": null,
        "CountryCode": "AF",
        "ISO": "AFG",
        "Parent": {
            "__type": "Region:#MEDEX.Library.Geo",
            "GeoType": 0,
            "ID": "6dc22edb-d711-4253-937f-242b0cd3c011",
            "Name": "Asia",
            "Code": "Asi"
        },
        "RegionID": "6dc22edb-d711-4253-937f-242b0cd3c011"
    },
    {
        "GeoType": 1,
        "ID": "3917c1c8-ee01-4e9b-8622-0fac9e9194ab",
        "Name": "Albania",
        "CapitalCity": null,
        "CountryBoundaries": null,
        "CountryCode": "AL",
        "ISO": "ALB",
        "Parent": {
            "__type": "Region:#MEDEX.Library.Geo",
            "GeoType": 0,
            "ID": "b7ebd500-45e6-4a48-a2ef-f38fe99e7352",
            "Name": "Europe",
            "Code": "Eur"
        },
        "RegionID": "b7ebd500-45e6-4a48-a2ef-f38fe99e7352"
    }
]

Мое определение объекта:

[DataContract]
public class Parent1
{
    [DataMember]
    public Dictionary<string, Type> __type { get; set; }
    [DataMember]
    public string ID { get; set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string GeoType { get; set; }
    [DataMember]
    public string Code { get; set; }
}

[DataContract]
public class Country
{
    [DataMember]
    public string ID { get; set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string GeoType { get; set; }
    [DataMember]
    public Parent1 Parent { get; set; }
    [DataMember]
    public string RegionID { get; set; }
    [DataMember]
    public string CountryCode { get; set; }
    [DataMember]
    public string ISO { get; set; }
}

всегда возникает ошибка:

{"Element ': Parent' содержит данные из типа, который соответствует имени 'http://schemas.datacontract.org/2004/07/MEDEX.Library.Geo:Region '. Десериализатору неизвестен какой-либо тип, который соответствует этому имени. Если вы с помощью DataContractSerializer или добавьте тип, соответствующий 'Region', в список известных типов - например, используя атрибут KnownTypeAttribute или добавив его в список известных типов, переданный в сериализатор. "}

Не могли бы вы предложить мне какое-нибудь решение. Я даже не понимаю, что означает эта ошибка. Пожалуйста, предложите.


person Saday Sarkar    schedule 09.09.2018    source источник
comment
Было бы полезно также добавить часть вашего кода, которая выполняет фактическую десериализацию.   -  person trashr0x    schedule 09.09.2018
comment
Связанные или похожие: parse.com: SerializationException десериализация объектов JSON со свойством «__type». Дает ли ответ на этот вопрос достаточно информации для решения вашей проблемы?   -  person dbc    schedule 09.09.2018


Ответы (2)


Добавить [KnownType (Region)] в атрибуты класса Parent1

person Deeksha Pandit    schedule 09.09.2018

Как объясняется в этом ответе на parse.com: SerializationException десериализация объектов JSON со свойством __type, ваша проблема в том, что "__type" является зарезервированным свойством для DataContractJsonSerializer. Он используется для идентификации производных типов полиморфных типов. Из документы:

Сохранение информации о типе

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

Подсказка типа очень похожа на атрибут xsi: type, определенный стандартом экземпляра схемы XML и используемый при сериализации / десериализации XML.

Члены данных с именем "__type" запрещены из-за потенциального конфликта с подсказкой типа.

Таким образом, вы не можете вручную добавить это свойство в свой класс и правильно его перевести.

Однако вы можете использовать обработку полиморфизма сериализатором для чтения и записи "__type" автоматически, определив иерархию классов регионов, в которых класс Region наследуется от некоторого базового типа, скажем RegionBase, на который ссылаются кому: Country.Parent:

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/MEDEX.Library.Geo")]
public class Country
{
    [DataMember]
    public string ID { get; set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string GeoType { get; set; }

    [DataMember]
    public RegionBase Parent { get; set; }

    [DataMember]
    public string RegionID { get; set; }
    [DataMember]
    public string CountryCode { get; set; }
    [DataMember]
    public string ISO { get; set; }
}

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/MEDEX.Library.Geo")]
[KnownType(typeof(Region))]
public class RegionBase
{
}

[DataContract(
    Name = "Region", 
    Namespace = "http://schemas.datacontract.org/2004/07/MEDEX.Library.Geo")]
public class Region : RegionBase
{
    [DataMember]
    public string ID { get; set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string GeoType { get; set; }
    [DataMember]
    public string Code { get; set; }
}

Затем десериализуйте как List<Country>, поскольку ваш внешний контейнер JSON представляет собой массив.

Примечания:

person dbc    schedule 09.09.2018
comment
@SadaySarkar - Рад помочь. Если на ваш вопрос ответят, отметьте его как таковой. - person dbc; 10.09.2018