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

C#如何将SmtpData与Proxy类序列化为同层级JSON

解决方法

首先明确:你当前的SmtpData类仅定义了嵌套的Proxy类,但没有声明该类型的实例成员,所以序列化时自然不会包含Proxy相关字段。要实现扁平化JSON输出,需要先给SmtpData添加Proxy类型的实例属性,再通过以下两种方式实现字段平级:


方案一:匿名类组合(简单直接,无需复用序列化逻辑)

步骤1:修改SmtpData类,添加Proxy实例字段

public class SmtpData
{
    public string id { get; set; }
    public string settingName { get; set; }
    public string host { get; set; }
    public int port { get; set; }
    public string username { get; set; }
    public string password { get; set; }
    public string senderName { get; set; }
    public string senderEmail { get; set; }
    public string senderMessageIdDomain { get; set; }
    public string senderReplyTo { get; set; }
    public string senderListUnsubscribe { get; set; }
    public bool isSecure { get; set; }
    public bool isUseProxy { get; set; }
    
    // 添加Proxy类型的实例字段,用于存储代理数据
    public Proxy ProxySettings { get; set; }

    public class Proxy
    {
        public string proxyhost { get; set; }
        public int proxyport { get; set; }
        public string proxyusername { get; set; }
        public string proxypassword { get; set; }
    }
}

步骤2:修改序列化代码,用匿名类合并所有字段

public void SaveSmtp(SmtpData data)
{
    // 用匿名类将SmtpData和Proxy的字段合并到同一层级
    var flattenedData = new 
    {
        data.id,
        data.settingName,
        data.host,
        data.port,
        data.username,
        data.password,
        data.senderName,
        data.senderEmail,
        data.senderMessageIdDomain,
        data.senderReplyTo,
        data.senderListUnsubscribe,
        data.isSecure,
        data.isUseProxy,
        // 处理Proxy为null的情况,避免空引用异常
        proxyhost = data.ProxySettings?.proxyhost,
        proxyport = data.ProxySettings?.proxyport ?? 0,
        proxyusername = data.ProxySettings?.proxyusername,
        proxypassword = data.ProxySettings?.proxypassword
    };

    var dataJson = JsonConvert.SerializeObject(flattenedData);
    string resultPath = Path.Combine(Helpers.SmtpPath, $"{data.id}.conf");
    File.WriteAllText(resultPath, dataJson);
}

方案二:自定义ContractResolver(适合多次复用场景)

如果需要在多个地方复用扁平化序列化逻辑,可以自定义ContractResolver自动处理嵌套字段的扁平化:

步骤1:添加自定义ContractResolver

public class FlattenProxyContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);

        // 隐藏SmtpData的ProxySettings字段,不直接序列化它
        if (member.DeclaringType == typeof(SmtpData) && member.Name == nameof(SmtpData.ProxySettings))
        {
            property.ShouldSerialize = _ => false;
        }

        return property;
    }

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var properties = base.CreateProperties(type, memberSerialization);

        // 为SmtpData添加Proxy类的所有属性,实现扁平化
        if (type == typeof(SmtpData))
        {
            var proxyProperties = base.CreateProperties(typeof(SmtpData.Proxy), memberSerialization);
            foreach (var proxyProp in proxyProperties)
            {
                var newProp = new JsonProperty
                {
                    PropertyName = proxyProp.PropertyName,
                    PropertyType = proxyProp.PropertyType,
                    Readable = true,
                    Writable = true,
                    ValueProvider = new ProxyValueProvider(proxyProp.ValueProvider)
                };
                properties.Add(newProp);
            }
        }

        return properties;
    }

    // 自定义值提供器,从ProxySettings中读取/设置字段值
    private class ProxyValueProvider : IValueProvider
    {
        private readonly IValueProvider _proxyValueProvider;

        public ProxyValueProvider(IValueProvider proxyValueProvider)
        {
            _proxyValueProvider = proxyValueProvider;
        }

        public object GetValue(object target)
        {
            var smtpData = (SmtpData)target;
            if (smtpData.ProxySettings == null)
            {
                // Proxy为空时返回对应类型的默认值
                return _proxyValueProvider.PropertyType.IsValueType ? Activator.CreateInstance(_proxyValueProvider.PropertyType) : null;
            }
            return _proxyValueProvider.GetValue(smtpData.ProxySettings);
        }

        public void SetValue(object target, object value)
        {
            var smtpData = (SmtpData)target;
            if (smtpData.ProxySettings == null)
            {
                smtpData.ProxySettings = new SmtpData.Proxy();
            }
            _proxyValueProvider.SetValue(smtpData.ProxySettings, value);
        }
    }
}

步骤2:修改序列化代码使用自定义Resolver

public void SaveSmtp(SmtpData data)
{
    var jsonSettings = new JsonSerializerSettings
    {
        ContractResolver = new FlattenProxyContractResolver()
    };
    var dataJson = JsonConvert.SerializeObject(data, jsonSettings);
    string resultPath = Path.Combine(Helpers.SmtpPath, $"{data.id}.conf");
    File.WriteAllText(resultPath, dataJson);
}

内容的提问来源于stack exchange,提问作者Oleg Buga

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:34:51