【问题标题】:Custom Json Serializer to serialize and deserialize all properties by ignoring the class attributes自定义 Json 序列化器通过忽略类属性来序列化和反序列化所有属性
【发布时间】:2017-04-06 04:25:54
【问题描述】:

我想序列化我的类的所有属性,但想在返回响应时隐藏一些属性。

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

感谢大家的回复。

【问题讨论】:

  • 你能发布你的json文件吗?
  • 也许你可以使用像return new { PlaceName = place.PlaceName };这样的匿名类?这是一个有点具体的解决方案,但无论如何......
  • @feeeper 我正在序列化泛型类中的对象。将每个属性映射到匿名对象是不可能的。我仍然感谢建议。

标签: c# json serialization asp.net-web-api


【解决方案1】:

您可以使用[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
{

}

【讨论】:

  • 但是使用 JsonSerializer 不会序列化属性。我需要序列化该属性。我只是不想回复它。
  • @SatishKumar - 误解了这个问题,所以我更新了它。
  • 我刚刚看到了您的解决方案。我做过同样的事情。非常感谢。
  • @SatishKumar - 酷。很高兴我能帮上忙。
  • 另请注意,如果您在第二个解决方案中继承了类似 CamelCaseContractResolver 的内容,则由于属性名称的大小写,它将无法工作。要修复它,请在 JsonIncludeContractResolver.CreateProperties 方法中更改此行: var property = actualProperties.FirstOrDefault(x => x.Name.Equals(jsonProperty.PropertyName, StringComparison.InvariantCultureIgnoreCase));
【解决方案2】:

一种可能的解决方案是使用匿名类:return new { PlaceName = place.PlaceName };

另一种解决方案是为您的类型创建自己的序列化程序并将其用于该类型。您可以找到自定义序列化程序的示例here

【讨论】:

    【解决方案3】:

    如果你的 Json 输出是 List&lt;Place&gt; 你可以试试:

            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);
            }
    

    【讨论】:

      猜你喜欢
      • 2016-03-05
      • 2013-04-07
      • 1970-01-01
      • 2021-05-26
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      • 2016-02-03
      • 2017-03-07
      相关资源
      最近更新 更多