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

时间:2015-04-03 21:46:30

标签: c# json json.net

这是我的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类的一个实例。换句话说,我希望我的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的版本字符串,剥去不必要的info,然后在继续填充我的模型之前将该字段解析为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之间有什么区别?

1 个答案:

答案 0 :(得分:1)

只需在您的Version媒体资源中添加适当的JsonConverterAttributePopulateObject即可使用该资源:

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,则可以将转换器添加到{ {3}},然后将其传递给JsonSerializerSettings.Converters

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