You need to enable JavaScript to run this app. 使用自定义JsonConverter反序列化时如何为JSON缺失属性赋值
优惠活动
大模型
产品
解决方案
定价
更多

使用自定义JsonConverter反序列化时如何为JSON缺失属性赋值

问题原因

你当前的方案不生效有两个核心原因:

  1. Newtonsoft.Json 默认仅当JSON字符串中存在对应属性键时,才会调用绑定到该属性的自定义JsonConverter,缺失属性不会触发属性级转换器执行
  2. 你编写的InternalIDConverter中CanConvert方法直接返回false,即使触发转换器逻辑也会直接被跳过

方案1:使用OnDeserialized特性回调(最简方案)

直接在实体类中添加反序列化完成后的自动回调方法,属于反序列化流程内的原生支持能力,无需额外配置:

using System.Runtime.Serialization;

public class TestClass
{
    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; }

    [OnDeserialized]
    internal void OnDeserializedMethod(StreamingContext context)
    {
        // 此处编写InternalID的赋值逻辑,支持基于当前对象的其他属性计算
        // 示例:用IdRemittance赋值,或者自定义自增逻辑均可
        InternalID = IdRemittance * 100;
    }
}

原反序列化调用代码无需任何修改即可生效。


方案2:自定义ContractResolver(无需修改实体类)

如果不能修改TestClass的定义,可以通过自定义合约解析器实现全局/指定类的缺失属性赋值:

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Reflection;
using System.Threading;

public class InternalIDContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        if (property.DeclaringType == typeof(TestClass) && property.PropertyName == nameof(TestClass.InternalID))
        {
            // 强制JSON缺失该属性时也填充默认值
            property.DefaultValueHandling = DefaultValueHandling.Populate;
            property.DefaultValueProvider = new InternalIDValueProvider();
        }
        return property;
    }
}

public class InternalIDValueProvider : IValueProvider
{
    // 示例:全局自增ID
    private int _incrementId = 0;
    public object GetValue(object target) => ((TestClass)target).InternalID;
    public void SetValue(object target, object value) => ((TestClass)target).InternalID = Interlocked.Increment(ref _incrementId);
}

反序列化时传入配置即可:

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 settings = new JsonSerializerSettings
    {
        ContractResolver = new InternalIDContractResolver()
    };
    var data = JsonConvert.DeserializeObject<List<TestClass>>(json, settings);
}

方案3:类级自定义JsonConverter

如果需要完全控制TestClass的反序列化流程,可以定义类级转换器:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class TestClassConverter : JsonConverter<TestClass>
{
    public override TestClass ReadJson(JsonReader reader, Type objectType, TestClass existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        JObject jObject = JObject.Load(reader);
        // 先反序列化所有JSON中存在的属性
        var instance = jObject.ToObject<TestClass>();
        // 给缺失的InternalID赋值
        instance.InternalID = 你的自定义赋值逻辑;
        return instance;
    }

    public override void WriteJson(JsonWriter writer, TestClass value, JsonSerializer serializer)
    {
        // 序列化逻辑按需实现
        serializer.Serialize(writer, value);
    }
}

反序列化时传入转换器即可:

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

内容的提问来源于stack exchange,提问作者Neeraj Kumar Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 07:36:08