2015-05-18 119 views
2

當我調用JsonConvert.SerializeObject(...)函數時,是否有任何方法將我的任何自定義屬性轉換爲某些東西?例如,我有一個類:如何將自定義屬性轉換爲Json字符串

class A 
{ 
    [UnitAttribute("---")] 
    public double? Ratio { get; set; } 
} 

當這種序列化類的任何實例,有沒有辦法把UnitAttribute的值轉換成JSON字符串?

我發現API中有一個IAttributeProvider接口。但似乎serialize函數並沒有真正使用它。

回答

0

做的是創建一個JsonConverter,增加屬性文字(我假設對應單位,在這種情況下)和轉換器連接到財產的最簡單的事情:

class A 
{ 
    [JsonConverter(typeof(UnitConverter), new object [] { "mm" })] 
    public double? Ratio { get; set; } 
} 

public class UnitConverter : JsonConverter 
{ 
    public string Units { get; set; } 

    string UnitsPostfix { get { return string.IsNullOrEmpty(Units) ? string.Empty : " " + Units; } } 

    public UnitConverter(string units) 
    { 
     this.Units = units; 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     throw new NotImplementedException(); // Not called when applied directly to a property. 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var jvalue = JValue.Load(reader); 
     if (jvalue.Type == JTokenType.String) 
     { 
      var s = (string)jvalue; 
      if (s.EndsWith(Units)) 
       jvalue = (JValue)s.Substring(0, s.LastIndexOf(Units)).Trim(); 
     } 
     return jvalue.ToObject(objectType); 

    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var jvalue = JValue.FromObject(value); 
     if (jvalue.Type == JTokenType.Null) 
      jvalue.WriteTo(writer); 
     else 
      writer.WriteValue((string)jvalue + UnitsPostfix); 
    } 
} 

通知我可以將單元字符串直接傳遞給屬性聲明中的轉換器構造函數。

如果你有大量的字段和屬性與UnitAttribute你的代碼庫,想轉換器會自動應用到所有的人,你可以從現有的合同解析器衍生而來,例如DefaultContractResolver定製IContractResolver適用必要的轉換器:

public class UnitContractResolver : DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     var property = base.CreateProperty(member, memberSerialization); 
     if (property.Converter == null && property.MemberConverter == null) 
     { 
      var attr = property.AttributeProvider.GetAttributes(typeof(UnitAttribute), true).Cast<UnitAttribute>().Where(a => !string.IsNullOrEmpty(a.Name)).FirstOrDefault(); 
      if (attr != null) 
      { 
       property.Converter = property.MemberConverter = new UnitConverter(attr.Name); 
      } 
     } 
     return property; 
    } 
} 

您可以使用合同解析器明確,像這樣:

 var settings = new JsonSerializerSettings() { ContractResolver = new UnitContractResolver() }; 

     var json = JsonConvert.SerializeObject(a, settings); 
     Debug.WriteLine(json); 
     var a11 = JsonConvert.DeserializeObject<A>(json, settings); 
     Debug.Assert(a.Ratio == a.Ratio); 

或將其設置在Json.net global settings自動使用。

相關問題