如何使用Json.net使用自定义绑定/映射填充模型?

如何使用Json.net使用自定义绑定/映射填充模型?

问题描述:

这里是我的JSON:如何使用Json.net使用自定义绑定/映射填充模型?

{ 
    "macAddress": "000A959D6816", 
    "softwareVersion": "1.2.1.5-UnnecessaryInfo", 
    "lastUpdated": "2015-04-03 20:46:40.375 -0500", 
    "charging": true 
} 

而且使用Json.NET,我可以做在C#中的以下内容:

namespace JsonTest 
{ 
    public class Tablet 
    { 
     public string MacAddress { get; set; } 
     public string SoftwareVersion { get; set; } 
     public DateTime LastUpdated { get; set; } 
     public bool Charging { get; set; } 
    } 

    public class TestClass 
    { 
     public void Test() 
     { 
      var json = "{ ... }"; // filled in with JSON info from above 
      var model = new Tablet(); 
      try 
      { 
       JsonConvert.PopulateObject(json, model); 
      } 
      catch (JsonSerializationException ex) 
      { 
       Console.WriteLine(ex); 
      } 
     } 
    } 
} 

到目前为止,一切都很好。我在这里的代码效果很好。它用来自Json的所有数据填充我的模型对象。但是,我并不真的希望我的模型的SoftwareVersion属性是一个字符串;我宁愿让它成为System.Version课程的一个实例。换句话说,我希望我的Tablet类看上去就像这样:

public class Tablet 
{ 
    public string MacAddress { get; set; } 
    public Version SoftwareVersion { get; set; } 
    public DateTime LastUpdated { get; set; } 
    public bool Charging { get; set; } 
} 

我不关心这个大干快上该版本字符串末尾附加不必要的信息,所以我想编写一些mapper/binder类来检查Json的版本字符串,去除不必要的信息,然后在继续填充模型之前将该字段解析为Version对象。我知道如何写个人解析方法;这将这样的伎俩:

private static Version ParseVersion(object versionObj) 
{ 
    var pattern = new Regex(@"^[\d.]+"); 
    var versionString = versionObj.ToString(); 
    if (!pattern.IsMatch(versionString)) return null; 

    var match = pattern.Match(versionString); 
    versionString = match.Groups[0].ToString(); 

    Version version; 
    Version.TryParse(versionString, out version); 
    return version; 
} 

什么我不知道是在哪里以及如何在JsonConvert过程“插入这”。我看到PopulateObject采用了可选的JsonSerializerSettings参数,并且又有几个不同的对象初始化参数,如BinderConverters。但我不确定要使用哪一个,也不知道如何写这些类来做我在这里描述的内容。我该怎么做? Binder和Converter之间有什么区别?

只需添加适当的JsonConverterAttributeVersion财产,PopulateObject将使用它:

public class Tablet 
{ 
    public string MacAddress { get; set; } 
    [JsonConverter(typeof(VersionConverter))] 
    public Version SoftwareVersion { get; set; } 
    public DateTime LastUpdated { get; set; } 
    public bool Charging { get; set; } 
} 

这里是实际的转换器:

public class VersionConverter : JsonConverter 
{ 
    private static Version ParseVersion(object versionObj) 
    { 
     var pattern = new Regex(@"^[\d.]+"); 
     var versionString = versionObj.ToString(); 
     if (!pattern.IsMatch(versionString)) 
      return null; 

     var match = pattern.Match(versionString); 
     versionString = match.Groups[0].ToString(); 

     Version version; 
     Version.TryParse(versionString, out version); 
     return version; 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(System.Version); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var token = JToken.Load(reader); 
     return ParseVersion((string)token); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var version = (Version)value; 
     if (version != null) 
      writer.WriteValue(value.ToString()); 
    } 
} 

您现在应该所有设置。

或者,如果你有一个Version属性出现在许多不同的容器类在一个复杂的对象图,你不想设置JsonConverterAttribute无处不在,您可以将转换器加到JsonSerializerSettings.Converters,然后传递到PopulateObject

JsonConvert.PopulateObject(json, model, new JsonSerializerSettings { Converters = new JsonConverter [] { new VersionConverter() } }); 
+0

漂亮!非常感谢! – SoaperGEM 2015-04-03 23:06:56