JsonConverter是脱敏手机号的合理选择,因其能精准作用于标注字段,避免手动替换漏嵌套、全局拦截误伤非敏感字段;PhoneMaskConverter需校验11位大陆手机号格式后掩码中间4位,空值与非法格式原样输出;JsonIgnore类删除字段而非变形,破坏接口契约;上线须严查null/空白处理、EF Core映射兼容性及Swagger示例渲染。

为什么 JsonConverter 是脱敏手机号的合理选择
直接在业务层手动替换手机号(比如用 string.Replace)容易漏掉嵌套对象、数组或动态属性;而全局序列化拦截(如 JsonSerializerOptions.Converters.Add)又太粗,可能误伤非敏感字段。用自定义 JsonConverter<string> 能精准控制「哪些 string 字段需要脱敏」——只要给对应属性打上 [JsonConverter(typeof(PhoneMaskConverter))],就只对它生效,不侵入逻辑,也不污染数据模型。
如何写一个只掩码中间4位的 PhoneMaskConverter
关键不是“怎么转 JSON”,而是「识别手机号格式 + 安全掩码」。不能简单截取第4~7位,得先校验是否为合法手机号(11位、以1开头),否则会把订单号、身份证后几位也乱遮。
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 继承
JsonConverter<string>,重写Read(反序列化时保持原值,一般不脱敏输入)和Write(序列化时处理) -
Write中用正则^1[3-9]\d{9}$判断是否为大陆手机号,匹配才执行value.Substring(0, 3) + "****" + value.Substring(7) - 注意:不要在
Write里 throw 异常,否则整个 JSON 序列化失败;不匹配就原样写入
public class PhoneMaskConverter : JsonConverter<string>
{
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
=> JsonSerializer.Deserialize<string>(ref reader, options); // 不做处理
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
if (!string.IsNullOrEmpty(value) && Regex.IsMatch(value, @"^1[3-9]d{9}$"))
value = value.Substring(0, 3) + "****" + value.Substring(7);
writer.WriteStringValue(value);
}
}
为什么不能直接用 JsonIgnore 或 JsonIgnoreCondition.WhenWritingNull
这两个是删字段,不是脱敏。用户需要看到「138****1234」这种占位信息来确认数据存在且格式正确,前端表单回显、日志追踪、审计报表都依赖这个模式。用 JsonIgnore 后字段消失,接口契约就变了,前端要额外判断字段是否存在,反而增加维护成本。
-
JsonIgnore→ 字段彻底不出现在 JSON 中 -
JsonIgnoreCondition.WhenWritingDefault对 string 意义不大(默认值是 null,但手机号通常非空) - 真正需要的是「值变形,字段保留」,只有
JsonConverter能做到这点
上线前必须检查的三个兼容点
脱敏逻辑一旦进序列化管道,就会影响所有使用该 converter 的场景,包括 Swagger 示例、单元测试断言、甚至 EF Core 的 JSON 列映射。最容易被忽略的是 null 和空白字符串处理:
- 传入
null或空串""时,Substring会抛ArgumentOutOfRangeException,必须前置判空 - 如果数据库字段允许空值,且你用的是 EF Core 7+ 的
HasConversion<string, JsonDocument>,确保 converter 不干扰原始存储值 - Swagger UI 默认用
System.Text.Json渲染示例,若没注册 converter,示例仍显示明文,需在Program.cs显式添加:options.Converters.Add(new PhoneMaskConverter())

















