You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义JSON转换器脱敏后序列化返回空字符串问题排查

问题分析与解决方案

你的代码返回空字符串的核心原因是无限递归调用导致序列化失败,另外还有一个需要注意的副作用问题,我来逐一拆解并给出修复方案:

核心问题:无限递归引发的序列化异常

在你的WriteJson方法中,你先调用了writer.WriteStartObject(),接着又调用serializer.Serialize(writer, value)。由于你已经将StudentJsonConverter注册到了序列化设置中,且CanConvert方法明确表示它可以处理Student类型,所以serializer.Serialize会再次触发当前转换器的WriteJson方法,形成无限递归。Json.NET在处理这种递归时会出现内部错误,最终返回空字符串作为失败结果。

另外,你直接修改了传入的student.Phone属性,这会改变原对象的内存状态——后续再使用这个Student实例时,它的Phone已经是脱敏后的值,这通常不是脱敏逻辑的预期行为(我们应该只在序列化输出中脱敏,不影响原对象)。

修复方案

这里提供两种可行的修复方式,你可以根据需求选择:

方案一:手动序列化所有属性(推荐,更可控)

直接手动写出每个属性的序列化逻辑,避免触发递归调用:

public class StudentJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value is not Student student)
        {
            // 非Student类型回退到默认序列化
            serializer.Serialize(writer, value);
            return;
        }

        writer.WriteStartObject();
        // 序列化Name属性
        writer.WritePropertyName(nameof(Student.Name));
        serializer.Serialize(writer, student.Name);
        // 脱敏后序列化Phone属性
        writer.WritePropertyName(nameof(Student.Phone));
        var maskedPhone = MaskString(student.Phone);
        serializer.Serialize(writer, maskedPhone);
        writer.WriteEndObject();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanConvert(Type objectType) => typeof(Student) == objectType;

    private static string MaskString(string sensitiveInformation) 
        => string.IsNullOrWhiteSpace(sensitiveInformation) ? null : new string('*', sensitiveInformation.Length);
}

方案二:使用不包含当前转换器的新序列化器

创建一个不包含StudentJsonConverter的新JsonSerializer实例,用来序列化脱敏后的对象副本,避免递归:

public class StudentJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value is not Student student)
        {
            serializer.Serialize(writer, value);
            return;
        }

        // 创建对象副本,避免修改原对象
        var serializedStudent = new Student
        {
            Name = student.Name,
            Phone = MaskString(student.Phone)
        };

        // 创建新的序列化器,排除当前转换器,避免递归
        var newSerializer = new JsonSerializer
        {
            ReferenceLoopHandling = serializer.ReferenceLoopHandling,
            // 可以复制原序列化器的其他设置
        };

        newSerializer.Serialize(writer, serializedStudent);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanConvert(Type objectType) => typeof(Student) == objectType;

    private static string MaskString(string sensitiveInformation) 
        => string.IsNullOrWhiteSpace(sensitiveInformation) ? null : new string('*', sensitiveInformation.Length);
}

验证效果

使用你的调用代码测试修复后的转换器,会得到正确的序列化结果:

{"Name":"name","Phone":"****"}

内容的提问来源于stack exchange,提问作者Buda Gavril

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:59:39