C# Newtonsoft如何将含多类型值的JSON数组转换为实体类
多类型值JSON结构映射方案
问题根源
你当前的实体定义和转换逻辑存在两个核心问题:
- 不能在同一个类的多个属性上标记指向同一JSON字段的
[JsonProperty("value")]特性,序列化器处理时会出现属性覆盖,最终只有最后一个声明的属性能正常赋值 - 自定义JsonConverter时没有先判断
value字段的实际Token类型做分支处理,只会按固定类型解析,自然无法适配数字、字符串、对象三种完全不同的值结构
实现步骤
1. 修正实体类定义
移除三个值属性上重复的[JsonProperty("value")]标记,避免映射冲突:
public class RandomProperties { [JsonProperty("name")] public string Name { get; set; } [JsonIgnore] public int? ValueInt { get; set; } [JsonIgnore] public string ValueString { get; set; } [JsonIgnore] public ValueObject ValueObject { get; set; } } public class ValueObject { [JsonProperty("type")] public string Type { get; set; } [JsonProperty("currency")] public string Currency { get; set; } [JsonProperty("amount")] public int? Amount { get; set; } [JsonProperty("typeId")] public string TypeId { get; set; } [JsonProperty("id")] public string ValueId { get; set; } }
2. 编写针对RandomProperties的自定义类型转换器
转换器核心逻辑是读取JSON片段后,先判断value字段的Token类型,再按对应类型解析赋值:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; public class RandomPropertiesConverter : JsonConverter<RandomProperties> { public override RandomProperties ReadJson(JsonReader reader, Type objectType, RandomProperties existingValue, bool hasExistingValue, JsonSerializer serializer) { JObject rawObj = JObject.Load(reader); RandomProperties result = new RandomProperties { Name = rawObj.Value<string>("name") }; JToken valueToken = rawObj["value"]; switch (valueToken.Type) { case JTokenType.Integer: result.ValueInt = valueToken.Value<int>(); break; case JTokenType.String: result.ValueString = valueToken.Value<string>(); break; case JTokenType.Object: result.ValueObject = valueToken.ToObject<ValueObject>(serializer); break; // 可按需扩展浮点数、布尔值等其他类型的处理分支 } return result; } public override void WriteJson(JsonWriter writer, RandomProperties value, JsonSerializer serializer) { JObject outputObj = new JObject { ["name"] = value.Name }; // 序列化时优先输出非空的value值 if (value.ValueInt.HasValue) { outputObj["value"] = value.ValueInt.Value; } else if (!string.IsNullOrEmpty(value.ValueString)) { outputObj["value"] = value.ValueString; } else if (value.ValueObject != null) { outputObj["value"] = JObject.FromObject(value.ValueObject, serializer); } outputObj.WriteTo(writer); } }
3. 注册转换器
在RandomProperties类上标记转换器特性即可生效:
[JsonConverter(typeof(RandomPropertiesConverter))] public class RandomProperties { // 类定义和之前保持一致 }
补充说明
如果你使用的是System.Text.Json,核心逻辑完全一致,只需要把解析逻辑从Newtonsoft的JObject换成System.Text.Json的JsonDocument即可,不需要调整分支判断的思路。
内容的提问来源于stack exchange,提问作者phicon
相关产品推荐
相关产品推荐

