如果属性未包含在使用自定义 JsonConverter 的 json 字符串中,如何在反序列化时设置值

问题描述

我有一个用于某个对象列表的 Json 字符串,此 Json 字符串不包含我的对象的属性之一。我正在寻找一种方法来在将 Json 字符串反序列化为对象时设置缺失的属性值。我有一个解决方法可以在反序列化完成后设置它,但如果我可以在反序列化时设置它,我会更喜欢它。

我尝试使用自定义 JsonConverter,但它不会作为相应的属性而不是 Json 字符串的一部分执行,如果我可以在反序列化时在缺失的属性中注入值,任何其他方式也都可以。

课程

public class TestClass
{
    [JsonConverter(typeof(InternalIDConverter))]
    public int InternalID { get; set; }
    public int IdRemittance { get; set; }
    public string IDCountry { get; set; }
    public string OperationAction { get; set; }
    public bool BusinessToBusiness { get; set; }
}

自定义 JsonConverter

public class InternalIDConverter : JsonConverter
{

    public override void WriteJson(JsonWriter writer,object value,JsonSerializer serializer)
    {
        throw new NotImplementedException("Not implemented yet");
    }

    public override object ReadJson(JsonReader reader,Type objectType,object existingValue,JsonSerializer serializer)
    {
        //Doing my work here
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override bool CanConvert(Type objectType)
    {
        return false;
    }
}

反序列化

    private void button11_Click(object sender,EventArgs e)
    {
        string json = "[{\"IDCountry\":\"AK\",\"BusinessToBusiness\":false,\"IdRemittance\":2,\"OperationAction\":\"U\"},{\"IDCountry\":\"AK\",\"BusinessToBusiness\":true,\"IdRemittance\":14,\"OperationAction\":\"U\"}]";

        var data = JsonConvert.DeserializeObject<List<TestClass>>(json);
    }

解决方法

您可以创建一个自定义转换器,让 Newtonsoft 读取和解析 json 中存在的所有属性,您可以手动为缺失的属性赋值:

public class TestClassConverter : JsonConverter<TestClass>
{
    private static readonly Random rand = new Random();
    public override TestClass ReadJson(JsonReader reader,Type objectType,TestClass existingValue,bool hasExistingValue,JsonSerializer serializer)
    {
        //Let Newtonsoft do the heavy lifting
        var jObject = JObject.Load(reader);
        var target = new TestClass();
        serializer.Populate(jObject.CreateReader(),target);

        //Set the intact property manually
        target.InternalID = rand.Next();
        return target;
    }

    public override void WriteJson(JsonWriter writer,TestClass value,JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

我使用了随机数,但您可以指定任何您想要的值。

用法:

var data = JsonConvert.DeserializeObject<List<TestClass>>(json,converters: new TestClassConverter());

使用这种方法,您不必用 TestClass 修饰 InternalIDJsonConverterAttribute 属性。


更新:非通用 JsonConverter 版本

public class TestClassConverter : JsonConverter
{
    private static readonly Random rand = new Random();
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(TestClass);
    }

    public override object ReadJson(JsonReader reader,object existingValue,JsonSerializer serializer)
    {
        var jObject = JObject.Load(reader);
        var target = new TestClass();
        serializer.Populate(jObject.CreateReader(),target);

        target.InternalID = rand.Next();
        return target;
    }

    public override void WriteJson(JsonWriter writer,object value,JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}