将两个值反序列化为同一属性
我有一个客户端可以调用两个不同版本的服务。
一项服务只发送一个值:
{ "value" : { ... } }
第二个服务总是返回多个值:
{ "values" : [ { ... }, { ... } ] }
理想情况下,我想在客户端类中使用单个对象来表示这一点,因此用户永远不会看到它是单个值还是多个值。
public class MyValues { public List Values { get; set; } public Thing Other { get; set; } }
我认为我能够实现这一目标的唯一方法是使用我应用于MyValues
的自定义JsonConverter
类,但我真的只想在我反序列化属性value
时做一些自定义操作。 我似乎无法弄清楚IContractResolver是否是更好的方法(例如以某种方式将幻像属性附加到MyValues,反序列化value
并将其放入Values
。
如果我创建一个自定义转换器,如何告诉它通常反序列化其他所有内容(例如,如果Other
具有额外的属性,请确保它们被正确处理,等等)
要创建一个自定义JsonConverter
, JsonConverter
类型的一些属性进行特殊处理,但对剩余部分使用默认处理,您可以将JSON加载到JObject
,分离并处理自定义属性,然后使用JsonSerializer.Populate()
填充JObject
的余数JsonSerializer.Populate()
,如下:
class MyValuesConverter : CustomPropertyConverterBase { protected override void ProcessCustomProperties(JObject obj, MyValues value, JsonSerializer serializer) { // Remove the value property for manual deserialization, and deserialize var jValue = obj.GetValue("value", StringComparison.OrdinalIgnoreCase).RemoveFromLowestPossibleParent(); if (jValue != null) { (value.Values = value.Values ?? new List()).Clear(); value.Values.Add(jValue.ToObject (serializer)); } } } public abstract class CustomPropertyConverterBase : JsonConverter where T : class { public override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var jObj = JObject.Load(reader); var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(objectType); var value = existingValue as T ?? (T)contract.DefaultCreator(); ProcessCustomProperties(jObj, value, serializer); // Populate the remaining properties. using (var subReader = jObj.CreateReader()) { serializer.Populate(subReader, value); } return value; } protected abstract void ProcessCustomProperties(JObject obj, T value, JsonSerializer serializer); public override bool CanWrite { get { return false; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } public static class JsonExtensions { public static JToken RemoveFromLowestPossibleParent(this JToken node) { if (node == null) return null; var contained = node.AncestorsAndSelf().Where(t => t.Parent is JContainer && t.Parent.Type != JTokenType.Property).FirstOrDefault(); if (contained != null) contained.Remove(); // Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should if (node.Parent is JProperty) ((JProperty)node.Parent).Value = null; return node; } }
您可以在JsonConverter
创建一个仅设置属性Value
,而不是编写MyValues
,如下所示:
public class MyValues { [JsonProperty] Stuff Value { set { (Values = Values ?? new List(1)).Clear(); Values.Add(value); } } public List Values { get; set; } public Thing Other { get; set; } }
如果用[JsonProperty]
标记,它可以是公共的或私有的。 在这种情况下,如果在JSON中遇到单例"value"
属性,Json.NET将调用Value
setter,如果遇到数组"values"
属性,则调用Values
setter。 由于属性是set-only,因此只会重新序列化数组属性。
上述就是C#学习教程:将两个值反序列化为同一属性分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/954342.html