Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在一个特定的序列化中序列化除特定属性以外的所有属性_C#_Json_Serialization_Json.net - Fatal编程技术网

C# 如何在一个特定的序列化中序列化除特定属性以外的所有属性

C# 如何在一个特定的序列化中序列化除特定属性以外的所有属性,c#,json,serialization,json.net,C#,Json,Serialization,Json.net,我有一个类似这样的对象(显然是简化的) 我希望ETag是对象json序列化的散列,省略ETag属性(以防止递归循环)。但是,我不能只使用[JsonIgnore]属性,因为在其他时候我希望能够用json序列化整个内容 所以我想要的是这样的东西 public string ETag { get { return Hash(JsonConvert.Serialize(this, p => p.Ignore(x=>x.ETag) )); }} 不幸的是,这不是一个存在的API。如何实

我有一个类似这样的对象(显然是简化的)

我希望ETag是对象json序列化的散列,省略ETag属性(以防止递归循环)。但是,我不能只使用
[JsonIgnore]
属性,因为在其他时候我希望能够用json序列化整个内容

所以我想要的是这样的东西

public string ETag { get {
   return Hash(JsonConvert.Serialize(this, p => p.Ignore(x=>x.ETag) ));
}}

不幸的是,这不是一个存在的API。如何实现类似的功能?

这并不漂亮,但在JSON序列化之后可以使用字符串替换。您可以将ETag设置为标记值,以便在序列化之后可以替换/删除该元素。

您可以使用自定义的
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;
    }
}
最后,这里是一个工作演示:

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:

不是最漂亮的解决方案,但我刚刚创建了一个类似的对象,可以从省略字段的主对象中构造,并在需要时序列化它。@BradleyDotNET是的,有很多方法可以使用automapper和其他东西来实现这一点,但维护起来很麻烦,因为我希望这个对象会更改lot。请给出代码?这样做仍然会调用Etag,导致递归循环。我知道有一种更好的方法来处理JsonSerializerSettings,我只是不知道如何避免使用字符串类型的属性名,可以使用表达式树解析来保持所有的强类型。我更新了布莱恩的例子:太好了。非常感谢!我不介意在本例中严格键入,因为在本例中,所有内容都是命名的属性实例的内部内容
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="
}