2017-04-19 66 views
1

我的目标是对没有任何属性和属性的属性进行序列化,这些属性具有特定的自定义属性。Json.Net中的自定义属性处理

对于下面的类:

public class Msg 
{ 
    public long Id { get; set; } 

    [CustomAttributeA] 
    public string Text { get; set; } 

    [CustomAttributeB] 
    public string Status { get; set; } 
} 

当我打电话的方法Serialize(object, CustomAttributeA),我想有以下输出:

{ 
    "Id" : someId, 
    "Text" : "some text" 
} 

当我打电话Serialize(object, CustomAttributeB),我想有以下几点:

{ 
    "Id" : someId, 
    "Status" : "some status" 
} 

我已经读过它有可能实现这通过创建自定义ContractResolver,但在这种情况下,我必须创建两个单独的合同解析器?

回答

3

你不需要两个单独的解析器来实现你的目标。只需定制ContractResolver泛型,其中type参数表示您在序列化时要查找的属性。

例如:

public class CustomResolver<T> : DefaultContractResolver where T : Attribute 
{ 
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
    { 
     IList<JsonProperty> list = base.CreateProperties(type, memberSerialization); 

     foreach (JsonProperty prop in list) 
     { 
      PropertyInfo pi = type.GetProperty(prop.UnderlyingName); 
      if (pi != null) 
      { 
       // if the property has any attribute other than 
       // the specific one we are seeking, don't serialize it 
       if (pi.GetCustomAttributes().Any() && 
        pi.GetCustomAttribute<T>() == null) 
       { 
        prop.ShouldSerialize = obj => false; 
       } 
      } 
     } 

     return list; 
    } 
} 

然后,你可以做一个辅助方法来创建解析器和序列化你的对象:

public static string Serialize<T>(object obj) where T : Attribute 
{ 
    JsonSerializerSettings settings = new JsonSerializerSettings 
    { 
     ContractResolver = new CustomResolver<T>(), 
     Formatting = Formatting.Indented 
    }; 
    return JsonConvert.SerializeObject(obj, settings); 
} 

当你想要序列,叫助手这样的:

string json = Serialize<CustomAttributeA>(msg); 

演示小提琴:https://dotnetfiddle.net/bRHbLy

+0

你也可以使这个通用 - 国际海事组织有点整洁'序列号(OBJ)'和'序列号(obj);' – Jamiec

+0

@贾米克好建议。我会更新我的答案。 –

+0

伟大的答案顺便说一句! – Jamiec