使用Newtonsoft.Json将JSON属性反序列化为子对象遇空值问题求助
解决JSON反序列化时Position属性为null的问题
这个问题的核心原因很明确:你的JSON结构里posx和posy是与pre同级的字段,但修改后的Vehicle类把这两个字段放到了嵌套的Position对象中。默认的Json.NET(Newtonsoft.Json)序列化器不会自动将平级的JSON属性映射到嵌套类的属性里,所以才会出现Position为null的情况。
下面提供两种实用的解决方法,都能让你复用Position类并正常完成反序列化:
方法一:自定义JsonConverter处理Vehicle类
创建一个专门的转换器,手动控制Vehicle对象的序列化和反序列化逻辑,把平级的posx和posy字段赋值给Position属性:
public class VehicleConverter : JsonConverter<Vehicle> { public override Vehicle ReadJson(JsonReader reader, Type objectType, Vehicle existingValue, bool hasExistingValue, JsonSerializer serializer) { // 先把JSON读取为JObject,方便提取字段 var jObject = JObject.Load(reader); var vehicle = new Vehicle { Prefix = jObject["pre"]?.ToString(), Position = new Position { Y = jObject["posx"]?.ToString(), X = jObject["posy"]?.ToString() } }; // 如果需要处理其他字段(比如JSON里的"a"),可以在这里添加逻辑 return vehicle; } public override void WriteJson(JsonWriter writer, Vehicle value, JsonSerializer serializer) { // 如果需要序列化Vehicle对象回JSON,也可以在这里定义逻辑 var jObject = new JObject(); jObject["pre"] = value.Prefix; if (value.Position != null) { jObject["posx"] = value.Position.Y; jObject["posy"] = value.Position.X; } jObject.WriteTo(writer); } }
然后在Vehicle类上标记使用这个转换器:
[JsonConverter(typeof(VehicleConverter))] public class Vehicle { [JsonProperty(PropertyName = "pre")] public string Prefix { get; set; } public Position Position { get; set; } }
这样反序列化时,转换器会自动把JSON里的posx和posy提取出来,创建Position对象并赋值给Vehicle的对应属性。
方法二:使用JsonConstructor构造函数
通过定义带参数的构造函数,并标记[JsonConstructor],让序列化器直接用JSON中的平级字段来初始化Position:
public class Vehicle { [JsonProperty(PropertyName = "pre")] public string Prefix { get; set; } public Position Position { get; set; } // 标记这个构造函数为JSON反序列化时使用的构造器 [JsonConstructor] public Vehicle(string pre, string posx, string posy) { Prefix = pre; Position = new Position { Y = posx, X = posy }; } // 需要保留一个无参构造函数,供序列化器内部使用(如果需要序列化的话) public Vehicle() {} }
这种方式更简洁,不需要额外写转换器,适合结构不复杂的场景。序列化器会自动匹配JSON中的字段名和构造函数的参数名(注意参数名要和JSON字段名一致,比如posx、posy),然后创建Position对象并赋值。
额外提示
如果JSON中还有其他不需要的字段(比如示例里的a),可以在Vehicle类中添加[JsonExtensionData]属性来忽略这些未知字段,避免反序列化出错:
[JsonExtensionData] private IDictionary<string, JToken> _extraData;
这样就能完美解决你的问题,让Position属性正常被赋值啦!
内容的提问来源于stack exchange,提问作者Roberto
相关产品推荐
相关产品推荐

