如何将JSON反序列化为包含自定义struct结构的C#对象?
问题原因
- Newtonsoft.Json(Json.NET)默认无法自动触发
Content到ContentStructure的隐式转换:当JSON中content节点为对象类型时,Json.NET只会尝试将节点属性与ContentStructure的成员直接匹配,而ContentStructure没有和JSON里id、duration对应的成员,最终只会生成默认值的ContentStructure实例,因此ContentClass为null。 - 当
content为字符串类型时,Json.NET可以匹配到你定义的string到ContentStructure隐式转换,因此ContentString可以正常赋值。 - 额外说明:
ContentStructure中的ContentClass、ContentString是公共字段而非属性,默认情况下Json.NET反序列化只会处理公共属性,即使类型匹配也不会自动给公共字段赋值。
解决方案
最稳妥的方式是为ContentStructure自定义JsonConverter,指定不同JSON节点类型的处理逻辑:
步骤1:实现自定义转换器
using Newtonsoft.Json; using Newtonsoft.Json.Linq; public class ContentStructureConverter : JsonConverter<ContentStructure> { public override ContentStructure ReadJson(JsonReader reader, Type objectType, ContentStructure existingValue, bool hasExistingValue, JsonSerializer serializer) { JToken token = JToken.Load(reader); // JSON节点是字符串,赋值给ContentString if (token.Type == JTokenType.String) { return token.ToObject<string>(); } // JSON节点是对象,反序列化为Content后赋值给ContentClass else if (token.Type == JTokenType.Object) { return token.ToObject<Content>(); } // 其他异常场景可按业务需求调整,这里返回默认值 return default; } public override void WriteJson(JsonWriter writer, ContentStructure value, JsonSerializer serializer) { // 序列化逻辑,按需实现 if (!string.IsNullOrEmpty(value.ContentString)) { writer.WriteValue(value.ContentString); } else { serializer.Serialize(writer, value.ContentClass); } } }
步骤2:注册转换器
两种注册方式二选一即可:
- 直接给
ContentStructure添加特性标记:
[JsonConverter(typeof(ContentStructureConverter))] public struct ContentStructure { public Content ContentClass; public string ContentString; public static implicit operator ContentStructure(Content content) => new ContentStructure { ContentClass = content }; public static implicit operator ContentStructure(string @string) => new ContentStructure { ContentString = @string }; }
- 反序列化时全局注册转换器:
var deserializeSettings = new JsonSerializerSettings { Converters = new List<JsonConverter> { new ContentStructureConverter() } }; var result = JsonConvert.DeserializeObject<Settings>(你的JSON字符串, deserializeSettings);
调整后即可同时兼容字符串和对象类型的content节点反序列化。
内容的提问来源于stack exchange,提问作者Erick
相关产品推荐
相关产品推荐

