2016-11-22 338 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; } 
} 

編輯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" 
    } 
] 

編輯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

可能的解決方案之一是使用匿名類: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

哼好吧你想返回一個PlaceName的數組... – Yanga

相關問題