默认应配置 NullValueHandling.Ignore 忽略 null 值;JsonProperty 可改名或忽略字段;反序列化失败多因类型不匹配,需用 JObject 处理动态结构。

JsonConvert.SerializeObject 序列化时忽略 null 值
默认情况下 JsonConvert.SerializeObject 会把值为 null 的属性也输出为 "PropertyName": null,但多数 API 接口或前端消费方不希望看到这些字段。直接忽略比手动删字段更可靠。
用法是传入 JsonSerializerSettings 并设置 NullValueHandling = NullValueHandling.Ignore:
var json = JsonConvert.SerializeObject(obj, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
- 注意:这个设置只影响序列化,反序列化不受影响
- 如果类里有可空类型(如
int?)且值为null,同样会被跳过 - 别和
DefaultValueHandling混用——后者针对的是默认值(如0、false),不是null
使用 JsonProperty 特性控制字段名和序列化行为
当 C# 属性名和 JSON 字段名不一致(比如 PascalCase → camelCase),或者想临时禁用某个属性的序列化,[JsonProperty] 是最轻量的解法。
常见写法:
public class User
{
[JsonProperty("user_id")]
public int Id { get; set; }
<pre class="brush:php;toolbar:false;">[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Nickname { get; set; }
[JsonIgnore]
public string InternalToken { get; set; }
}
-
[JsonProperty("xxx")]改字段名,仅作用于当前属性 -
[JsonIgnore]完全跳过该属性(序列化和反序列化都忽略) - 若同时用了
[JsonProperty]和[JsonIgnore],后者优先级更高,会报编译警告
JsonConvert.DeserializeObject 反序列化失败的典型原因
最常见的错误是 Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value,往往不是 JSON 格式真错了,而是类型不匹配。
- JSON 里是字符串
"age": "25",但 C# 属性定义为int Age→ 直接抛异常,不会自动转类型 - JSON 数组
"tags": ["a","b"]对应 C# 的List→ 类型错,也会崩 - 遇到不确定结构的 JSON(比如字段可能为
string或object),别硬套强类型,改用JObject或JToken先解析再判断
临时救急可加 JsonSerializerSettings.Error 回调捕获并跳过出错字段,但不推荐长期依赖。
用 JObject 动态处理未知或混合结构的 JSON
当接口返回的 JSON 结构不稳定(比如某些字段有时是数组、有时是对象,或字段名带变量),强类型反序列化会频繁报错。JObject 提供运行时灵活访问能力。
示例:读取一个可能为字符串或对象的 data 字段:
var jObj = JObject.Parse(jsonString);
var dataToken = jObj["data"];
<p>if (dataToken.Type == JTokenType.Object)
{
var name = dataToken["name"]?.ToString();
}
else if (dataToken.Type == JTokenType.String)
{
var rawValue = dataToken.ToString();
}</p>
-
JObject不需要提前定义类,适合配置、日志、第三方回调等场景 - 性能比强类型略低,但换来的是鲁棒性——尤其在对接外部 API 时,字段变动频繁
- 别用
.ToString()直接拼 JSON 字符串,要用JObject.ToString(Formatting.None)避免意外换行缩进
真正难的不是学会这四种方式,而是每次拿到新 JSON 时,能快速判断该用哪种:固定结构就上 DeserializeObject,字段名不一致就加 [JsonProperty],结构松散就切到 JObject,而 NullValueHandling 几乎该成为所有序列化的默认配置。











