DataContractJsonSerializer генерирует исключение InvalidCastException для членов различных типов - PullRequest
0 голосов
/ 30 декабря 2010

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

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

или

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

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

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

1 Ответ

0 голосов
/ 24 июля 2011

У меня была похожая ситуация, когда 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();
    }
}
...