我如何使用 Json.net 来填充带有自定义 bindings/mappings 的模型?
How can I use Json.net to populate a model with custom bindings/mappings?
这是我的 JSON:
{
"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 class 的一个实例。换句话说,我希望我的 Tablet
class 看起来更像这样:
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 class从 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;
}
我不知道在 Json 转换过程中在哪里以及如何 "plug this in"。我看到 PopulateObject
有一个可选的 JsonSerializerSettings parameter, and in turn that has several different object initializer parameters like Binder and Converters。但我不确定使用哪个,也不确定如何编写这些 classes 中的任何一个来完成我在这里描述的内容。我该怎么做? Binder 和 Converter 有什么区别?
只需添加一个合适的JsonConverterAttribute
to your Version
property, and 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
, then pass that to PopulateObject
:
JsonConvert.PopulateObject(json, model, new JsonSerializerSettings { Converters = new JsonConverter [] { new VersionConverter() } } );
这是我的 JSON:
{
"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 class 的一个实例。换句话说,我希望我的 Tablet
class 看起来更像这样:
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 class从 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;
}
我不知道在 Json 转换过程中在哪里以及如何 "plug this in"。我看到 PopulateObject
有一个可选的 JsonSerializerSettings parameter, and in turn that has several different object initializer parameters like Binder and Converters。但我不确定使用哪个,也不确定如何编写这些 classes 中的任何一个来完成我在这里描述的内容。我该怎么做? Binder 和 Converter 有什么区别?
只需添加一个合适的JsonConverterAttribute
to your Version
property, and 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
, then pass that to PopulateObject
:
JsonConvert.PopulateObject(json, model, new JsonSerializerSettings { Converters = new JsonConverter [] { new VersionConverter() } } );