2010-12-30 4 views
0

DataContractJsonSerializerで逆シリアル化したい文字列があります。 JSON文字列には、時にはオブジェクトでも、他の時にも文字列になるメンバーがあります。これと同じように:DataContractJsonSerializerはさまざまな型のメンバーのInvalidCastExceptionをスローします

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

または

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

私は(のは、そのクラスInnerを呼びましょう)は、第2のケース内のオブジェクトの構造を知っているが、どのようにDataContractJsonSerializer 2つの可能な種類のオブジェクトを変換することができますか?

stringからInnerに変換する明示的かつ暗黙的なキャスト演算子を作成しようとしましたが、ヒットしません。 InvalidCastExceptionが投げつけられ続けます。

答えて

0

私は、APIがオブジェクトの配列を返していた場合と同様の状況、または結果が1つしかない場合は配列内にない単一のオブジェクトを返しました。私はこれを行うためにDataContractJsonSerializerを完全に取得することができませんでした。私はJSON.NETライブラリに切り替える必要があり、JsonConvertersを使って動作させるにはちょっとした手間がかかりました。

DataContractで、 'c'をInner型として宣言します。デシリアライザはインナーをデシリアライズしようとしたときに

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

次にトークンタイプを調べて、正しいことを行うためにJsonConverterを書きます。

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(); 
    } 
} 
関連する問題