2014-09-30 49 views
6

我有一個對象,它看起來是這樣的(顯然簡體)如何序列化所有,但一個特定的屬性在一個特定的序列化

public class Person { 
    public string Name { get; set; } 
    public int Age { get; set; } 
    public string ETag { get { return ... } } 
} 

我想什麼是ETag的是JSON序列化的哈希該對象省略了ETag屬性(以防止遞歸循環)。但是,我不能僅僅使用[JsonIgnore]屬性,因爲在其他時候我希望能夠將json序列化爲整個事物。

所以,我想是這樣的

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

這是不幸的是沒有存在的API。我將如何實現類似的東西?

+0

不是最漂亮的解決方案,但我剛剛創建了一個可以從省略領域的主要一個構造相似的對象,序列化,當我需要它。 – BradleyDotNET 2014-09-30 22:24:24

+0

@BradleyDotNET是很多方式來做到這一點與automapper和東西,但它成爲一個麻煩,因爲我期望這個對象改變很多 – 2014-09-30 22:25:28

回答

5

您可以使用自定義IContractResolver以編程方式忽略對象的屬性。所以我認爲我會採取的方法是創建一個簡單的解析器,可以明確地忽略單個類型的單個屬性(顯然,如果需要,可以擴展此屬性),然後創建一個可以使用該解析器序列化的幫助器方法。使用ETag屬性中的幫助器方法,您很好。

下面是解析器代碼:

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方法):

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=" 
} 

小提琴:https://dotnetfiddle.net/YgVJ4K

+2

如果你想避免字符串類型的屬性名稱,你可以使用表達式樹解析來保持它所有的強類型。我在這裏更新了Brian的例子:https://dotnetfiddle.net/G5u8NJ – bitwalker 2014-10-01 00:54:42

+0

@bitwalker很好地完成了。 – 2014-10-01 02:01:19

+0

太好了。非常感謝!我不介意在這種情況下輸入字符串,因爲在這種情況下,所有屬性都被命名爲屬性實例 – 2014-10-01 02:11:53

0

它並不漂亮,但可以在JSON序列化之後使用字符串替換。您可以將ETag設置爲標記值,​​以便在序列化後可以替換/移除該元素。

+0

請給代碼?這樣做仍然會調用Etag導致遞歸循環。我知道有更好的方法來處理JsonSerializerSettings,我只是不知道具體如何 – 2014-09-30 22:42:04

相關問題