JObject 是反序列化后动态访问 JSON 字段的首选:需用 JObject.Parse()、启用 dynamic 后可 obj.name 访问,但须注意大小写匹配和空值判断;强类型反序列化更高效安全,适用于结构固定场景。

用 JsonConvert.DeserializeObject<object></object> 无法直接访问字段?
因为 object 是静态类型,反序列化后只是个 Object 实例,没有属性成员,obj.Name 会编译报错。必须用支持运行时属性访问的类型。
必须用 JObject 或 ExpandoObject 才能点出字段
JObject 是最常用、最稳的选择:它来自 Newtonsoft.Json,原生支持索引器和动态语法(启用 dynamic 后可直接 obj.Name);ExpandoObject 虽然也是 dynamic 友好,但需手动解析,容易漏字段或类型错位。
- 确保已安装
Newtonsoft.JsonNuGet 包(.NET Core 6+ 若用System.Text.Json,默认不支持动态对象) - 用
JObject.Parse(jsonString),不是DeserializeObject<jobject></jobject>—— 前者更直接,后者多一层封装且无必要 - 若想用
dynamic语法(如dynamic obj = JObject.Parse(...); Console.WriteLine(obj.name);),需引用using Newtonsoft.Json.Linq;,且项目支持 C# 4.0+ 动态绑定
JObject 和 dynamic 混用时的典型错误
常见现象:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Newtonsoft.Json.Linq.JObject' does not contain a definition for 'xxx'。根本原因是字段名大小写不匹配(JSON 是严格区分大小写的),或字段不存在但没做空判断。
- 检查原始 JSON 中字段名是否真为
name,而不是Name、NAME或带空格/特殊字符 - 别直接写
obj.name.ToString()—— 先用obj["name"]判断是否存在,再转类型:obj["name"]?.ToString() - 嵌套对象要逐层判空:
obj["user"]?["profile"]?["age"]?.Value<int>()</int>,否则一环为空就抛异常
性能与场景取舍:什么时候不该用 JObject
如果只是读一两个固定字段,且结构稳定,硬编码为具体类(如 User)+ JsonConvert.DeserializeObject<user></user> 更快、更安全、IDE 有提示。用 JObject 的真实场景是:字段名动态(比如配置项 key 来自数据库)、结构不确定(不同 API 版本返回字段不同)、或需遍历所有属性做通用处理。
-
JObject解析比强类型慢约 2–3 倍(实测千条中等 JSON),内存占用略高 - .NET 6+ 的
System.Text.Json不提供等效JObject,强行用JsonNode(.NET 6 引入)虽可动态访问,但语法啰嗦:root["name"]?.GetValueKind() == JsonValueKind.String,远不如JObject直观 - 如果项目已用
System.Text.Json且不想引入 Newtonsoft,可用JsonDocument.Parse+RootElement.GetProperty("name"),但它只读、不可修改,也不支持dynamic
字段名大小写、嵌套空值、序列化库选择——这三个点卡住的人最多,其他都是顺带的事。


















