2016-07-22 3 views
1

それは次のようなJSON文字列をどのようにスカラー値として、オブジェクトの複雑なプロパティをシリアル化

{ 
    "Name":"Johny Bravo", 
    "ComplexProperty":{ 
     "Prop1":"value1", 
     "Prop2":"value2", 
     "Prop3":100 
    } 
} 

になりますとき

var a = new A(); 
var str = JsonConvert.SerializeObject(a); 

シリアライズされた私たちは、次のクラス定義

public class A 
{ 
    public string Name { get; } = "Johny Bravo"; 
    public B ComplexProperty { get; } = new B(); 
} 

public class B 
{ 
    public string Prop1 { get; } = "value1"; 
    public string Prop2 { get; } = "value2"; 
    public int Prop3 { get; } = 100; 

    public override string ToString() 
    { 
     return this.Prop3.ToString(); 
    } 
} 

を持っていると仮定ComplexPropertyをスカラー値としてシリアライズさせるか?望ましい結果は、このいずれかである必要があります

{ 
    "Name":"Johny Bravo", 
    "ComplexProperty":100 
} 

答えて

2

この問題の適切な解決策は、タイプを処理できるカスタムJsonConverterを使用することです。特にAクラスとBクラスのコードを制御できない場合。ここでは、サンプルコード

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var a = new A(); 
      var str = JsonConvert.SerializeObject(a, new JsonSerializerSettings() 
      { 
       Converters = new List<JsonConverter>() 
       { 
        new BTypeJsonConverter() 
       } 
      }); 
     } 
    } 

    public class A 
    { 
     public string Name { get; } = "Johny Bravo"; 
     public B ComplexProperty { get; } = new B(); 
    } 

    public class B 
    { 
     public string Prop1 { get; } = "value1"; 
     public string Prop2 { get; } = "value2"; 
     public int Prop3 { get; } = 100; 

     public override string ToString() 
     { 
      return this.Prop3.ToString(); 
     } 
    } 

    public class BTypeJsonConverter : JsonConverter 
    { 
     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      var b = value as B; 
      if (b == null) return; 
      writer.WriteValue(b.ToString()); 
     } 

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 
      JsonSerializer serializer) 
     { 
      throw new NotImplementedException(); 
     } 

     public override bool CanConvert(Type objectType) 
     { 
      return objectType == typeof(B); 
     } 
    } 
} 
3

あなたが値 をintにBクラスを割り当てているので、あなたのコードがコンパイルされません。しかし、私は、私はあなたが望む結果を得ると思う:

class Program 
    { 


    static void Main(string[] args) 
    { 
     var a = new A(); 
     var str = JsonConvert.SerializeObject(a); 
     Console.Write(str); 
    } 
} 

public class A 
{ 
    public string Name { get; } = "Johny Bravo"; 
    [JsonIgnore] 
    public B ComplexProperty { get; } = new B(); 
    [JsonProperty("ComplexProperty")] 
    public int complexValue => ComplexProperty.Prop3; 
} 

public class B 
{ 
    public string Prop1 { get; } = "value1"; 
    public string Prop2 { get; } = "value2"; 
    public int Prop3 { get; } = 100; 

    public override string ToString() 
    { 
     return this.Prop3.ToString(); 
    } 
} 

したいので、あなたのオブジェクトが平らになるように(1レベルの深さだけ)、あなたはAクラスのプロパティを持つ必要があります。 jsonの結果にあなたの複雑なオブジェクトを持たせたくないので、あなたはそれを無視しなければならず、Jsonの結果に同じ名前を付ける必要があるので、jsonのシリアライザに、必要な名前

+0

ご回答ありがとうございます。私はそれのようなものを考えましたが、もしAとBが第三者図書館から来たのであれば? –

+0

@MihailShishkovそれは何の違いもありません。 getメソッドがあるので、必要な値を持つことができます。 のようにpublic int complexValue => SomeMethod(someObjects); –

+0

サードパーティのライブラリにAとBがあるということは、コードを変更できないことを意味します。したがって、新しい属性やプロパティを追加するだけでは不十分です。シリアル化のためだけにAのアダプタを用意すれば、あなたの提案はうまくいくはずです。 Aがたくさんのプロパティを持つ本当のクラスであると想像してください:) –

0

は、別のプロパティを追加し、最初の1にシリアライズPropertyNameを設定します。クラスAが第三者のライブラリから提供されている場合は、Aから派生したクラスを作成し、新しいプロパティを追加します。

public class A 
{ 
    public string Name { get; } = "Johny Bravo"; 
--> [JsonIgnore] 
    public B ComplexProperty { get; } = new B(); 
-->[JsonProperty(PropertyName = "ComplexProperty")] 
--> public string ComplexPropertyText { get{ return ComplexProperty.ToString(); } } 
} 

public class B 
{ 
    public string Prop1 { get; } = "value1"; 
    public string Prop2 { get; } = "value2"; 
    public int Prop3 { get; } = 100; 

    public override string ToString() 
    { 
     return this.Prop3.ToString(); 
    } 
} 
関連する問題