You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 21:01:36