c# json序列化和反序列化 newtonsoft.json

来源:这里教程网 时间:2026-02-21 17:38:03 作者:

为什么 JsonConvert.SerializeObject 会把 DateTime 转成带斜杠的字符串而不是 ISO 8601?

Newtonsoft.Json 默认用

JavaScriptDateTimeConverter
,它把
DateTime
序列化为
"/Date(1234567890000)/"
格式——这是早期 ASP.NET WebForms 的遗留行为,现代 API 基本不认这个。

解决方法:全局配置
JsonSerializerSettings
,显式指定
DateFormatHandling = DateFormatHandling.IsoDateFormat
或者单次调用时传入设置:
JsonConvert.SerializeObject(obj, new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.IsoDateFormat });
注意:如果服务端要求 UTC 时间,别忘了在序列化前调用
.ToUniversalTime()
,否则本地时区时间会被当成 UTC 写入

反序列化时遇到 "Cannot deserialize the current JSON array" 错误

这个错误通常不是因为 JSON 格式错,而是类型不匹配。比如你传入的是 JSON 数组

[{"id":1},{"id":2}]
,但代码里写了
JsonConvert.DeserializeObject<user>(json)</user>
(期望单个对象)。

检查 JSON 开头是
[
还是
{
:数组对应
List<t></t>
T[]
,对象对应
T
不要靠猜测类型,用
JToken.Parse(json).Type
先确认结构:
var token = JToken.Parse(json);<br>Console.WriteLine(token.Type); // 输出 Array 或 Object
如果 JSON 结构不确定(比如可能单个或多个),先反序列化为
JToken
,再分支处理

如何忽略某个属性不参与序列化?

最常用的是

[JsonIgnore]
特性,但它只对 public 属性/字段生效。如果字段是 private 或需要运行时判断是否忽略,就得换方式。

静态忽略:在属性上加
[JsonIgnore]
,简单直接
public class User {<br>    public string Name { get; set; }<br>    [JsonIgnore]<br>    public string Password { get; set; }<br>}
动态忽略:用
ShouldSerialize{PropertyName}()
方法(命名必须严格匹配),返回
false
就跳过
public bool ShouldSerializePassword() => !IsAdmin;
注意:
[JsonIgnore]
private set
字段无效;若需控制私有字段,改用
JsonPropertyAttribute
+
DefaultValueHandling.Ignore
配合
DefaultValue

使用 JsonConvert.DeserializeObject 时泛型类型 T 为空或 null 怎么办?

这不是 Newtonsoft 的 bug,而是 C# 泛型擦除机制导致:运行时无法获取

T
的完整类型信息,尤其当
T
是接口(如
IList<string></string>
)或抽象类时,反序列化会失败并抛出
JsonSerializationException

接口/抽象类必须配合
TypeNameHandling
才能还原具体类型,但开启它有安全风险(反序列化任意类型),不推荐用于不可信输入
更稳妥的做法:用具体类型反序列化,例如把
IList<string></string>
改成
List<string></string>
如果必须用接口且来源可信,可临时启用:
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };<br>JsonConvert.DeserializeObject<IList<string>>(json, settings);

真正容易被忽略的是:即使类型写对了,如果 JSON 中字段名和 C# 属性名大小写不一致(比如 JSON 是

user_name
,C# 是
UserName
),默认不会自动映射——得加
[JsonProperty("user_name")]
或统一设
ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() }

相关推荐