如何在一个特定序列化中序列化除特定属性外的所有属性
本文关键字:序列化 属性 一个 | 更新日期: 2023-09-27 18:25:12
我有一个对象看起来像这样(明显简化了)
public class Person {
public string Name { get; set; }
public int Age { get; set; }
public string ETag { get { return ... } }
}
我希望ETag是省略ETag属性的对象的json序列化的散列(以防止递归循环)。但是,我不能只使用[JsonIgnore]
属性,因为在其他时候我希望能够json序列化整个内容。
所以我想要的是类似的东西
public string ETag { get {
return Hash(JsonConvert.Serialize(this, p => p.Ignore(x=>x.ETag) ));
}}
不幸的是,它不是存在的API。我将如何实现类似的目标?
您可以使用自定义IContractResolver
以编程方式忽略对象的属性。因此,我认为我会采取的方法是创建一个简单的解析器,它可以专门忽略单个类型上的单个属性(显然,如果需要,您可以扩展它),然后创建一个可以使用该解析器进行序列化的助手方法。在ETag
属性中使用helper方法,就可以开始了。
以下是解析器的代码:
class IgnorePropertyResolver : DefaultContractResolver
{
Type targetType;
string targetPropertyName;
public IgnorePropertyResolver(Type targetType, string propertyName)
{
this.targetType = targetType;
this.targetPropertyName = propertyName;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
if (targetType == type)
{
props = props.Where(p => p.PropertyName != targetPropertyName).ToList();
}
return props;
}
}
这是helper方法(我还在其中抛出了一个Hash helper方法,因为你在问题中没有定义它):
static class JsonHelper
{
public static string Serialize(object target, string propertyToIgnore)
{
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new IgnorePropertyResolver(target.GetType(), propertyToIgnore);
return JsonConvert.SerializeObject(target, settings);
}
public static string Hash(string json)
{
using (var sha = new SHA1Managed())
{
return Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(json)));
}
}
}
最后,这里有一个工作演示:
class Program
{
static void Main(string[] args)
{
Person p = new Person { Name = "Joe", Age = 26 };
Console.WriteLine("Etag = " + p.ETag);
Console.WriteLine();
Console.WriteLine(JsonConvert.SerializeObject(p, Formatting.Indented));
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string ETag
{
get { return JsonHelper.Hash(JsonHelper.Serialize(this, "ETag")); }
}
}
输出:
Etag = T99YVDlrbZ66YL2u5MYjyIyO4Qk=
{
"Name": "Joe",
"Age": 26,
"ETag": "T99YVDlrbZ66YL2u5MYjyIyO4Qk="
}
Fiddle:https://dotnetfiddle.net/YgVJ4K
它并不漂亮,但您可以在JSON序列化后使用字符串替换。您可以将ETag设置为标记值,以便在序列化后可以替换/删除该元素。