2010-12-30 3 views
0

Существует часть строки, которую я хотел бы десериализовать с помощью DataContractJsonSerializer. В строке JSON есть член, который иногда может быть объектом или строкой другого времени. Как так:DataContractJsonSerializer выбрасывает InvalidCastException для членов различного типа

{ a: 1, b: 2, c: "c" } 

или

{ a: 1, b: 2, c: {c1: 3, c2: 4} } 

Я знаю структуру объекта во втором случае (давайте назовем этот класс Inner), но как можно DataContractJsonSerializer преобразовать объект двух возможных типов?

Я попытался сделать явный и неявный оператор литья, чтобы преобразовать из string в Inner, но он не попадает. InvalidCastException продолжает бросать.

ответ

0

У меня была аналогичная ситуация, когда API возвращал либо массив объектов, либо только один объект не в массиве, если был только один результат. Мне не удалось заставить DataContractJsonSerializer сделать это. Мне пришлось переключиться на библиотеку JSON.NET и немного поиграть с JsonConverters, чтобы заставить ее работать.

В вашем DataContract объявите 'c' как тип Inner.

[DataMember(Name = "c")] 
public Inner C { get; set; } 

Затем написать JsonConverter изучить тип маркеров и сделать правильную вещь, когда десериализатор пытается десериализация Inner.

internal class StringOrInnerConverter : JsonConverter { 
    public override bool CanConvert(Type objectType) { 
     return objectType == typeof(Inner); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { 
     var ser = new JsonSerializer(); 

     if (reader.TokenType == JsonToken.StartObject) { 
      var inn = ser.Deserialize<Inner>(reader); 
      return inn; 
     } else if (reader.TokenType == JsonToken.String) { 
      var str = ser.Deserialize<string>(reader); 
      return (Inner)str; // Or however you want to convert string to Inner 
     } else { 
      return default(Inner); 
     } 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { 
     throw new System.NotImplementedException(); 
    } 
} 
Смежные вопросы