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

如何使用Newtonsoft JSON.NET根据枚举动态修改JSON属性名

嘿,这个需求我之前也碰到过,用Newtonsoft JSON.NET完全可以搞定,给你两种实用的实现思路,按需选就行:

1. 先准备基础定义

首先得把枚举和各个支付方式的详情模型定义好,强类型处理更安全:

// 支付方式枚举
public enum PaymentMethodEnum
{
    Cash,
    Card,
    Debit,
    Check
}

// 各支付方式的详情类
public class CashDetails { } // Cash没有额外属性,空类即可

public class CardDetails
{
    public string Authorization { get; set; }
    public string Bin { get; set; }
    public string Reference { get; set; }
}

public class DebitDetails
{
    public string DocumentType { get; set; }
    public string DocumentNumber { get; set; }
    public string Account { get; set; }
}

public class CheckDetails
{
    // 根据实际需求补充Check的属性,比如支票号、银行代码等
    public string CheckNumber { get; set; }
    public string BankCode { get; set; }
}

2. 方式一:手动构建JObject(简单直观,适合快速实现)

这种方式直接根据枚举值动态拼接JSON结构,不需要额外配置序列化器:

public static string GeneratePaymentJson(PaymentMethodEnum paymentType, object paymentDetails)
{
    var rootObj = new JObject();
    var paymentMethodObj = new JObject();

    switch (paymentType)
    {
        case PaymentMethodEnum.Cash:
            // Cash可以传null,默认生成空对象
            paymentMethodObj.Add("Cash", JObject.FromObject(paymentDetails ?? new CashDetails()));
            break;
        case PaymentMethodEnum.Card:
            // 校验传入的详情类型,避免错误
            if (paymentDetails is not CardDetails cardDetails)
                throw new ArgumentException("Card支付必须传入CardDetails对象");
            paymentMethodObj.Add("Card", JObject.FromObject(cardDetails));
            break;
        case PaymentMethodEnum.Debit:
            if (paymentDetails is not DebitDetails debitDetails)
                throw new ArgumentException("Debit支付必须传入DebitDetails对象");
            paymentMethodObj.Add("Debit", JObject.FromObject(debitDetails));
            break;
        case PaymentMethodEnum.Check:
            if (paymentDetails is not CheckDetails checkDetails)
                throw new ArgumentException("Check支付必须传入CheckDetails对象");
            paymentMethodObj.Add("Check", JObject.FromObject(checkDetails));
            break;
        default:
            throw new NotImplementedException($"不支持的支付方式:{paymentType}");
    }

    rootObj.Add("PaymentMethod", paymentMethodObj);
    // 格式化输出,方便阅读,不需要的话可以用Formatting.None
    return rootObj.ToString(Formatting.Indented);
}

使用示例:

// Cash示例
var cashJson = GeneratePaymentJson(PaymentMethodEnum.Cash, null);
// 输出结果:{"PaymentMethod": {"Cash": {}}}

// Card示例
var cardInfo = new CardDetails
{
    Authorization = "####",
    Bin = "####",
    Reference = "00#####"
};
var cardJson = GeneratePaymentJson(PaymentMethodEnum.Card, cardInfo);

// Debit示例
var debitInfo = new DebitDetails
{
    DocumentType = "DNI",
    DocumentNumber = "##########3",
    Account = "xxxx-####"
};
var debitJson = GeneratePaymentJson(PaymentMethodEnum.Debit, debitInfo);

3. 方式二:自定义JsonConverter(适合序列化完整请求对象)

如果你的业务是围绕一个包含支付类型和详情的主对象展开,自定义转换器可以让序列化过程更自动化:

首先定义主请求类:

public class PaymentRequest
{
    public PaymentMethodEnum PaymentType { get; set; }
    public object PaymentDetails { get; set; }
}

然后实现自定义转换器:

public class PaymentRequestConverter : JsonConverter<PaymentRequest>
{
    // 序列化逻辑:把PaymentRequest转成目标JSON结构
    public override void WriteJson(JsonWriter writer, PaymentRequest value, JsonSerializer serializer)
    {
        var rootObj = new JObject();
        var paymentMethodObj = new JObject();

        switch (value.PaymentType)
        {
            case PaymentMethodEnum.Cash:
                paymentMethodObj.Add("Cash", value.PaymentDetails == null ? new JObject() : JObject.FromObject(value.PaymentDetails));
                break;
            case PaymentMethodEnum.Card:
                if (value.PaymentDetails is not CardDetails card)
                    throw new JsonSerializationException("Card支付需要传入CardDetails类型的详情");
                paymentMethodObj.Add("Card", JObject.FromObject(card));
                break;
            case PaymentMethodEnum.Debit:
                if (value.PaymentDetails is not DebitDetails debit)
                    throw new JsonSerializationException("Debit支付需要传入DebitDetails类型的详情");
                paymentMethodObj.Add("Debit", JObject.FromObject(debit));
                break;
            case PaymentMethodEnum.Check:
                if (value.PaymentDetails is not CheckDetails check)
                    throw new JsonSerializationException("Check支付需要传入CheckDetails类型的详情");
                paymentMethodObj.Add("Check", JObject.FromObject(check));
                break;
            default:
                throw new JsonSerializationException($"不支持的支付方式:{value.PaymentType}");
        }

        rootObj.Add("PaymentMethod", paymentMethodObj);
        rootObj.WriteTo(writer);
    }

    // 反序列化逻辑:把JSON转回PaymentRequest对象(可选,根据业务需求实现)
    public override PaymentRequest ReadJson(JsonReader reader, Type objectType, PaymentRequest existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var rootObj = JObject.Load(reader);
        var paymentMethodObj = (JObject)rootObj["PaymentMethod"];
        // 获取PaymentMethod下的唯一键,判断支付类型
        var paymentTypeKey = paymentMethodObj.Properties().First().Name;
        var paymentType = Enum.Parse<PaymentMethodEnum>(paymentTypeKey);

        var request = new PaymentRequest { PaymentType = paymentType };

        // 根据支付类型反序列化对应的详情
        switch (paymentType)
        {
            case PaymentMethodEnum.Cash:
                request.PaymentDetails = paymentMethodObj["Cash"].ToObject<CashDetails>();
                break;
            case PaymentMethodEnum.Card:
                request.PaymentDetails = paymentMethodObj["Card"].ToObject<CardDetails>();
                break;
            case PaymentMethodEnum.Debit:
                request.PaymentDetails = paymentMethodObj["Debit"].ToObject<DebitDetails>();
                break;
            case PaymentMethodEnum.Check:
                request.PaymentDetails = paymentMethodObj["Check"].ToObject<CheckDetails>();
                break;
        }

        return request;
    }
}

使用示例:

var paymentRequest = new PaymentRequest
{
    PaymentType = PaymentMethodEnum.Debit,
    PaymentDetails = new DebitDetails
    {
        DocumentType = "DNI",
        DocumentNumber = "##########3",
        Account = "xxxx-####"
    }
};

var serializerSettings = new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new PaymentRequestConverter() },
    Formatting = Formatting.Indented
};

var json = JsonConvert.SerializeObject(paymentRequest, serializerSettings);
// 输出就是你要的Debit对应的JSON结构

小提示

  • 如果后续要扩展Check的属性,只需要修改CheckDetails类,然后在switch分支里对应处理就行,扩展性很好
  • 手动构建JObject的方式适合简单场景,自定义Converter适合需要序列化/反序列化完整业务对象的场景
  • 可以根据业务需求添加更多的参数校验,避免非法输入导致的异常

内容的提问来源于stack exchange,提问作者Leo Jim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:56:32