2016-11-22 3 views
1

クラスのすべてのプロパティをシリアル化する必要がありますが、応答を返しながらいくつかのプロパティを非表示にします。カスタムJsonシリアライザは、クラス属性を無視してすべてのプロパティを直列化および逆シリアル化します。

私は、シリアライズにNewtonSoft.Json.Netを使用しています。

たとえば、以下のクラスでは、両方のプロパティをシリアル化する必要がありますが、PlaceNameを返すだけです。

これを行う方法はありますか?

[DataContract] 
public class Place 
{ 
    [DataMember(EmitDefaultValue = false)] 
    public int PlaceId { get; set; } 

    [DataMember(EmitDefaultValue = false, Order = 1)] 
    public string PlaceName { get; set; } 
} 

EDIT 1:

以下は、私の現在のJSONファイルです。

[ 
    { 
    "placeId": 1, 
    "placeName": "Malacca" 
    }, 
    { 
    "placeId": 2, 
    "placeName": "Kuala Lumpur" 
    }, 
    { 
    "placeId": 3, 
    "placeName": "Genting Highlands" 
    }, 
    { 
    "placeId": 4, 
    "placeName": "Singapore" 
    }, 
    { 
    "placeId": 5, 
    "placeName": "Penang" 
    }, 
    { 
    "placeId": 6, 
    "placeName": "Perak" 
    }, 
    { 
    "placeId": 8, 
    "placeName": "Selangor" 
    } 
] 

EDIT 2:私はいくつかの研究で解決策を見つけたソリューション

を発見しました。

すべてのプロパティを直列化および逆シリアル化して渡すカスタムコントラクトリゾルバを作成しました。

以下は私のコード

public class AllPropertiesResolver : DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     JsonProperty property = base.CreateProperty(member, memberSerialization); 
     property.Ignored = false; 
     return property; 
    } 
} 

であり、以下に、私はそれを呼び出したコードです。

JsonConvert.SerializeObject(object, new JsonSerializerSettings() { ContractResolver = new AllPropertiesResolver() }); 
JsonConvert.DeserializeObject<T>(stream, new JsonSerializerSettings() { ContractResolver = new AllPropertiesResolver() }); 

ありがとうございます。

+0

をあなたのJSONファイルを投稿することができますか? – Yanga

+1

'return new {PlaceName = place.PlaceName};'のような匿名クラスを使うことができますか?これは少し具体的な解決策ですが、とにかく... – feeeper

+0

@feeeperジェネリッククラスのオブジェクトをシリアル化しています。各プロパティを匿名オブジェクトにマッピングすることはできません。私は提案に感謝します。 –

答えて

1

解決策の1つは、匿名のクラスを使用することです:return new { PlaceName = place.PlaceName };

別の解決策は、自分のタイプの独自のシリアライザを作成し、そのタイプに使用することです。あなたが見つけることができるカスタムシリアライザの例here

4

[JsonIgnore]を使用できます。 asp.net-web-apiであなたの質問にタグを付けたので、私はあなたが実際に使っていると思います。以下はコントローラがJsonIgnoreのプロパティを除くモデル全体を返す例です。カスタムContractResolverを使用することで、すべてのプロパティを含めるようにシリアライザを設定します(JsonIgnoreを取得しても)。また、応答を返すときはデフォルトのContractResolverを使用します。

ただし、デフォルトの動作よりも優先されます。だから、ちょうどIgnored = falseを設定するよりも、いくつかのチェックを追加したいかもしれません。

public class PlaceController : ApiController 
{ 
    [HttpGet] 
    public IHttpActionResult Get() 
    { 
     var json = "[{\"placeId\": 1,\"placeName\": \"Malacca\"},{\"placeId\": 2,\"placeName\": \"Kuala Lumpur\"},{\"placeId\": 3,\"placeName\": \"Genting Highlands\"},{\"placeId\": 4,\"placeName\": \"Singapore\"},{\"placeId\": 5,\"placeName\": \"Penang\"},{\"placeId\": 6,\"placeName\": \"Perak\"},{\"placeId\": 8,\"placeName\": \"Selangor\"}]"; 

     var settings = new JsonSerializerSettings(); 
     settings.ContractResolver = new IncludeAllPropertiesContractResolver(); 

     var places = JsonConvert.DeserializeObject<Place[]>(json, settings); 
     return Ok(places); 
    } 
} 


public class IncludeAllPropertiesContractResolver : DefaultContractResolver 
{ 
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
    { 
     IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization); 

     // Or other way to determine... 
     foreach (var jsonProperty in properties) 
     { 
      // Include all properties. 
      jsonProperty.Ignored = false; 
     } 
     return properties; 
    } 
} 

[DataContract] 
public class Place 
{ 
    [JsonIgnore] 
    [DataMember(EmitDefaultValue = false)] 
    public int PlaceId { get; set; } 

    [DataMember(EmitDefaultValue = false, Order = 1)] 
    public string PlaceName { get; set; } 
} 

出力:

[ 
{ 
"placeName": "Malacca" 
}, 
{ 
"placeName": "Kuala Lumpur" 
}, 
{ 
"placeName": "Genting Highlands" 
}, 
{ 
"placeName": "Singapore" 
}, 
{ 
"placeName": "Penang" 
}, 
{ 
"placeName": "Perak" 
}, 
{ 
"placeName": "Selangor" 
} 
] 

それとも、少し反射を気にしない場合。以下ではJsonInclude -attributeを使用します。デフォルトの動作はJsonIgnoreよりも優先されます。

public class JsonIncludeContractResolver : DefaultContractResolver 
{ 
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
    { 
     IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization); 

     var actualProperties = type.GetProperties(); 

     foreach (var jsonProperty in properties) 
     { 
      // Check if it got our JsonInclude attribute. 
      var property = actualProperties.FirstOrDefault(x => x.Name == jsonProperty.PropertyName); 
      if (property != null && property.GetCustomAttribute(typeof(JsonInclude)) != null) 
      { 
       jsonProperty.Ignored = false; 
      } 
     } 
     return properties; 
    } 
} 

[DataContract] 
public class Place 
{ 
    [JsonInclude] // Will override JsonIgnore. 
    [JsonIgnore] 
    [DataMember(EmitDefaultValue = false)] 
    public int PlaceId { get; set; } 

    [DataMember(EmitDefaultValue = false, Order = 1)] 
    public string PlaceName { get; set; } 
} 

public class JsonInclude : Attribute 
{ 

} 
+0

しかし、JsonSerializerを使用してプロパティをシリアル化していません。私はプロパティをシリアル化する必要があります。私はちょうどそれを返信したくない。 –

+0

@SatishKumar - 誤解されたので、私はそれを更新しました。 – smoksnes

+0

私はちょうどあなたの解決策を見た。私は同じことをした。どうもありがとうございます。 –

0

あなたのJSON出力がList<Place>であれば、あなたは試すことができます:

 var json = "[{\"placeId\":1,\"placeName\":\"Malacca\"},{\"placeId\":2,\"placeName\":\"Kuala Lumpur\"},{\"placeId\":3,\"placeName\":\"Genting Highlands\"},{\"placeId\":4,\"placeName\":\"Singapore\"},{\"placeId\":5,\"placeName\":\"Penang\"},{\"placeId\":6,\"placeName\":\"Perak\"},{\"placeId\":8,\"placeName\":\"Selangor\"}]"; 

     var Places = JsonConvert.DeserializeObject<List<Place>>(json); 

     foreach (var place in Places) 
     { 
      Console.WriteLine(place.PlaceName); 
     } 
+0

ハムok PlaceNameの配列を返したい – Yanga

関連する問題