处理同一属性具有混合单值和数组值的 JSON 数据
问题:
处理 JSON 数据时,经常会遇到同一属性既可以表示为单个值,也可以表示为值数组的情况。例如,考虑从 SendGrid API 获取的以下有效负载:
[ { "email": "[email protected]", "timestamp": 1337966815, "category": [ "newuser", "transactional" ], "event": "open" }, { "email": "[email protected]", "timestamp": 1337966815, "category": "olduser", "event": "open" } ]
“category” 属性说明了这个问题。对于某些项目,它是一个字符串,而对于其他项目,它是一个字符串数组。JSON.NET 提供了两种处理这种不一致性的方法:修改传入的数据或配置 JSON.NET 以接受差异。
解决方案:自定义 JsonConverter
推荐的方法是使用自定义 JsonConverter。让我们定义一个类来反序列化数据:
class Item { [JsonProperty("email")] public string Email { get; set; } [JsonProperty("timestamp")] public int Timestamp { get; set; } [JsonProperty("event")] public string Event { get; set; } [JsonProperty("category")] [JsonConverter(typeof(SingleOrArrayConverter<string>))] public List<string> Categories { get; set; } }
对于可能是单个项目或数组的属性(在本例中为“category”),我们将其定义为 List
以下是转换器的实现:
class SingleOrArrayConverter<T> : JsonConverter { public override bool CanConvert(Type objectType) { return (objectType == typeof(List<T>)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JToken token = JToken.Load(reader); if (token.Type == JTokenType.Array) { return token.ToObject<List<T>>(); } if (token.Type == JTokenType.Null) { return null; } return new List<T> { token.ToObject<T>() }; } public override bool CanWrite { get { return false; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }
此转换器确定传入的标记是数组还是单个项目,并相应地进行处理。如果它是数组,则将其转换为 List
用法和输出
要使用自定义转换器,请按如下所示更新反序列化代码:
string json = @"[ ... same as before ... ]"; List<Item> list = JsonConvert.DeserializeObject<List<Item>>(json);
程序将正确反序列化 JSON 数据,“category” 属性将针对单个情况和数组情况适当地填充为字符串列表。
这种方法提供了一种灵活的方法来处理同一属性具有混合值类型的 JSON 数据,无需修改数据或由于处理不一致而导致潜在的数据丢失。
以上是如何处理同一属性的混合单和数组值的JSON数据?的详细内容。更多信息请关注PHP中文网其他相关文章!