簡體   English   中英

定制Json Serializer,通過忽略類屬性來序列化和反序列化所有屬性

[英]Custom Json Serializer to serialize and deserialize all properties by ignoring the class attributes

我想序列化類的所有屬性,但想在返回響應時隱藏一些屬性。

我正在使用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() });

謝謝大家的回應。

您可以使用[JsonIgnore] 由於您使用asp.net-web-api標記了問題,因此我認為您實際上已經在使用它。 因此,下面是一個示例,其中控制器將返回整個模型,但JsonIgnore屬性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
{

}

一種可能的解決方案是使用匿名類: return new { PlaceName = place.PlaceName };

另一種解決方案是為您的類型創建自己的序列化器,並將其用於類型。 您可以在此處找到自定義序列化程序的示例

如果您的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);
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM