C#中如何将RDAP响应的vcardArray改为强类型字段?
解决RDAP响应中vcardArray的强类型反序列化问题
针对RDAP响应里vcardArray的弱类型问题,我们可以通过自定义Json转换器+强类型类的方式解决,避免正则解析的繁琐和不可靠性,具体实现步骤如下:
1. 定义vCard强类型类
根据RDAP返回的vCard结构(遵循vCard 4.0规范),定义对应的实体类:
// vCard根结构,对应vcardArray的外层数组 public class VcardRoot { public string Type { get; set; } // 固定为"vcard" public List<VcardProperty> Properties { get; set; } = new(); } // 单个vCard属性项(如fn、adr、version等) public class VcardProperty { public string Name { get; set; } // 属性名,例如"fn" public Dictionary<string, object> Parameters { get; set; } // 属性参数(通常为空对象) public string ValueType { get; set; } // 值类型,例如"text" public object Value { get; set; } // 属性值:可能是单个字符串或字符串数组(如地址字段) }
2. 实现自定义Json转换器
因为vcardArray是嵌套数组结构,不是标准JSON对象,需要自定义转换器来解析:
public class VcardRootConverter : JsonConverter<VcardRoot> { public override VcardRoot ReadJson(JsonReader reader, Type objectType, VcardRoot existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.TokenType != JsonToken.StartArray) throw new JsonSerializationException("vcardArray必须是数组格式"); var array = JArray.Load(reader); if (array.Count < 2 || array[0].ToString() != "vcard") throw new JsonSerializationException("无效的vcardArray格式"); var vcardRoot = new VcardRoot { Type = array[0].ToString() }; // 遍历所有属性项(外层数组的第二个元素开始) foreach (var propArray in array[1].Children<JArray>()) { if (propArray.Count < 3) continue; var property = new VcardProperty { Name = propArray[0].ToString(), Parameters = propArray[1].ToObject<Dictionary<string, object>>(serializer), ValueType = propArray[2].ToString() }; // 处理值:如果属性数组长度大于3,说明是多段值(如地址) property.Value = propArray.Count > 3 ? propArray.Skip(3).Select(v => v.ToString()).ToList() : propArray[3].ToString(); vcardRoot.Properties.Add(property); } return vcardRoot; } public override void WriteJson(JsonWriter writer, VcardRoot value, JsonSerializer serializer) { // 若需要序列化回JSON,可在此实现对应逻辑,示例场景暂省略 throw new NotImplementedException(); } }
3. 修改Entity类的vcardArray字段
将原List<object>类型替换为VcardRoot,并指定自定义转换器:
public class Entity { // 保留原有其他字段 [JsonConverter(typeof(VcardRootConverter))] public VcardRoot vcardArray { get; set; } }
4. 强类型使用示例
反序列化后可直接通过强类型访问vCard数据,无需正则处理:
// 假设已获取RDAP响应的JSON字符串 var rdapResponse = JsonConvert.DeserializeObject<RdapResponse>(jsonString); var targetEntity = rdapResponse.Entities.FirstOrDefault(); if (targetEntity?.vcardArray != null) { // 获取组织名称(fn属性) var orgName = targetEntity.vcardArray.Properties.First(p => p.Name == "fn").Value.ToString(); // 获取地址字段(adr属性为字符串数组) var addressParts = targetEntity.vcardArray.Properties.First(p => p.Name == "adr").Value as List<string>; if (addressParts != null) { var city = addressParts[3]; // 对应Boston var state = addressParts[4]; // 对应MA } }
注意事项
- 若需支持更多vCard属性的特殊值类型(如日期、URI),可扩展
VcardProperty的Value属性为泛型或更具体的类型; - 若需要将强类型vCard序列化回JSON格式,需完善转换器的
WriteJson方法; - 测试时覆盖不同的vCard属性格式,确保转换器兼容性。
内容的提问来源于stack exchange,提问作者user4779
相关产品推荐
相关产品推荐

