2016-11-22 241 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

相关问题