30人参与 • 2026-03-05 • Javascript
在进行代码迁移前,必须牢记这两个库在底层设计哲学上的根本分歧,这是几乎所有反序列化报错的根源:
| 场景 | newtonsoft.json (旧) | system.text.json (新) | 迁移备注 |
|---|---|---|---|
| 指定 json 键名 | [jsonproperty("name")] | [jsonpropertyname("name")] | 必须逐个替换。 |
| 忽略某字段 | [jsonignore] | [jsonignore] | 基本一致。 |
| 忽略空值 (null) | nullvaluehandling.ignore | 全局 options: defaultignorecondition = jsonignorecondition.whenwritingnull | 推荐在全局 jsonserializeroptions 中统一配置,减少序列化体积。 |
| 忽略默认值 | defaultvaluehandling.ignore | [jsonignore(condition = jsonignorecondition.whenwritingdefault)] | 新版将其合并到了 jsonignore 特性中。 |
问题描述:很多第三方 api 返回的小驼峰命名(如 userprofile),而 c# 模型是大驼峰命名(如 userprofile)。老版能完美自动映射,新版只要大小写不一致,直接反序列化为 null。
解决方案:在反序列化时,务必全局传入配置允许忽略大小写:
var options = new jsonserializeroptions { propertynamecaseinsensitive = true };
var result = jsonserializer.deserialize<mymodel>(jsonstring, options);
问题描述:对接外部不可控 api 时经常遇到格式不规范的数据。比如 id 字段有时是数字 ("id": 123),有时是字符串 ("id": "a-123");金额字段有时返回字符串 ("price": "19.99"),甚至用空字符串表示无数据 ("discount": "")。
新版只要遇到 json 节点类型与 c# 声明类型(如 string 对 int)不匹配,会直接抛出 jsonexception 崩溃。
解决方案:不要指望内置配置项能完美兜底(尤其是处理空字符串),建议直接封装自定义 jsonconverter。
用途:当 c# 模型定义为 string id,但外部 json 传入的是数字 123 时,自动将其转换为 "123" 且不报错。
using system;
using system.text.json;
using system.text.json.serialization;
namespace yournamespace.helpers
{
public class numbertostringconverter : jsonconverter<string?>
{
public override string? read(ref utf8jsonreader reader, type typetoconvert, jsonserializeroptions options)
{
if (reader.tokentype == jsontokentype.number) return reader.getint64().tostring();
if (reader.tokentype == jsontokentype.string) return reader.getstring();
return null;
}
public override void write(utf8jsonwriter writer, string? value, jsonserializeroptions options)
{
if (value == null) writer.writenullvalue();
else writer.writestringvalue(value);
}
}
}
// 实体类使用方式:[jsonconverter(typeof(numbertostringconverter))]
用途:当 c# 模型定义为 decimal? price,但 json 传入的是 "19.99" 或者是代表无值的空字符串 "" 时,安全地将其转换为 decimal 或 null。
using system;
using system.text.json;
using system.text.json.serialization;
namespace yournamespace.helpers
{
// 注意:泛型必须与属性类型完全一致(此处为可空类型 decimal?)
public class stringtodecimalconverter : jsonconverter<decimal?>
{
public override decimal? read(ref utf8jsonreader reader, type typetoconvert, jsonserializeroptions options)
{
if (reader.tokentype == jsontokentype.number) return reader.getdecimal();
if (reader.tokentype == jsontokentype.string)
{
string? strvalue = reader.getstring();
// 很多老旧 api 喜欢用空字符串代表没有值,安全处理为 null
if (string.isnullorwhitespace(strvalue)) return null;
if (decimal.tryparse(strvalue, out decimal result)) return result;
}
return null;
}
public override void write(utf8jsonwriter writer, decimal? value, jsonserializeroptions options)
{
// 序列化时,可根据对接方 api 的偏好决定是否转回字符串
if (value.hasvalue) writer.writestringvalue(value.value.tostring("0.00"));
else writer.writenullvalue();
}
}
}
// 实体类使用方式:[jsonconverter(typeof(stringtodecimalconverter))]
// 警告:此转换器必须配合 public decimal? price { get; set; } 使用!不可用于非空 decimal。
问题描述:当模型中存在 public object value { get; set; }(例如用于接收不确定结构的数据、扩展字段 metadata 等),老版会猜测并转化为 string, int 等具体 c# 基础类型。而新版会统一将其解析为 jsonelement 结构体。
危险操作:任何试图将反序列化后的 object 强转回基础类型的操作都会导致运行时崩溃!
string val = (string)model.value; -> 抛出 invalidcastexceptionif (model.value is string s) -> 永远为 falsestring val = model.value as string; -> 永远返回 null安全的操作规范(提取真实数据) :
纯中转/序列化/拼接场景(最稳妥) :利用 convert.tostring() 提取字面量。
// 完美应对 jsonelement。 // 配合 invariantculture 防止部署在不同国家服务器时,小数点被转换成逗号的问题。 string safestringvalue = convert.tostring(model.value, cultureinfo.invariantculture)!;
业务逻辑需严格执行类型判断:通过检查 jsonelement.valuekind。
if (model.value is jsonelement element)
{
if (element.valuekind == jsonvaluekind.string)
string s = element.getstring();
else if (element.valuekind == jsonvaluekind.number)
decimal d = element.getdecimal();
}
问题描述:老版会自动序列化和反序列化 public string name; 这种公开的字段 (fields)。新版默认只处理属性 (properties) ,即带有 { get; set; } 的成员,对字段直接静默忽略,不报错但数据会全部丢失。
解决方案:
最佳实践:将实体类的成员强制重构为标准属性 { get; set; }。
兼容方案:若存在大量历史代码难以修改,需在全局 options 中显式开启:
var options = new jsonserializeroptions { includefields = true };
在未来遇到 system.text.json 抛出异常或反序列化出 null 时,请严格遵循以下排查步骤:
到此这篇关于c#中newtonsoft.json 到 system.text.json 迁移避坑指南的文章就介绍到这了,更多相关c#中newtonsoft.json到system.text.json 迁移内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论