C#中动态JSON序列化反序列化:按需构造请求Payload
解决C#中动态JSON请求Payload的Data结构问题
我需要通过C#提交JSON请求,请求Payload中的data部分需根据业务规则动态变更。已知所有可能的data结构,但请求中仅需使用符合规则的对应结构。
请求示例
示例1
{"activity": {"referenceId": "","data": {"rents": 0.0,"wages": 0.0}}}
示例2
{"activity": {"referenceId": "","data": {"transport": 0.0,"salaries": 0.0}}}
示例3
{"activity": {"referenceId": "","data": {"water": 0.0,"miscellaneous": 0.0}}}
现有POCO代码
我已经按常规方式定义了POCO类,但不知道怎么满足动态结构的需求。原本想创建一个“主”Data对象,只传递需要的属性,但在这里卡住了。现有代码如下:
public class Rootobject { public Activity activity { get; set; } } public class Activity { public string referenceId { get; set; } public Data data { get; set; } } public class Data // 继承这个主类行不通 { public float water { get; set; } public float miscellaneous { get; set; } public float transport { get; set; } public float salaries { get; set; } public float rents { get; set; } public float wages { get; set; } }
可行解决方案
方案1:使用继承+JsonSubTypes(强类型场景推荐)
为每种data结构定义独立子类,借助JsonSubTypes库(或System.Text.Json的多态序列化特性)控制序列化逻辑:
using JsonSubTypes; using Newtonsoft.Json; public class Rootobject { public Activity activity { get; set; } } public class Activity { public string referenceId { get; set; } [JsonConverter(typeof(JsonSubtypes))] [JsonSubtypes.KnownSubType(typeof(RentWagesData), "rentWages")] [JsonSubtypes.KnownSubType(typeof(TransportSalariesData), "transportSalaries")] [JsonSubtypes.KnownSubType(typeof(WaterMiscData), "waterMisc")] public BaseData data { get; set; } } public abstract class BaseData { } public class RentWagesData : BaseData { public float rents { get; set; } public float wages { get; set; } } public class TransportSalariesData : BaseData { public float transport { get; set; } public float salaries { get; set; } } public class WaterMiscData : BaseData { public float water { get; set; } public float miscellaneous { get; set; } }
序列化时传入对应子类实例,即可生成仅包含目标属性的JSON。
方案2:使用匿名类型(快速实现)
无需定义复杂类结构,直接根据业务规则创建匿名类型:
// 业务规则要求传入rents和wages的场景 var payload = new { activity = new { referenceId = "", data = new { rents = 0.0f, wages = 0.0f } } }; // 序列化生成JSON string json = JsonConvert.SerializeObject(payload);
这种方式简单直接,适合无需复用结构的临时场景。
方案3:使用Dictionary<string, float>(灵活场景)
将data定义为字典类型,动态添加需要的键值对:
public class Rootobject { public Activity activity { get; set; } } public class Activity { public string referenceId { get; set; } public Dictionary<string, float> data { get; set; } } // 使用示例 var activity = new Activity { referenceId = "", data = new Dictionary<string, float> { {"rents", 0.0f}, {"wages", 0.0f} } }; string json = JsonConvert.SerializeObject(new Rootobject { activity = activity });
该方式灵活性最高,适合属性组合多变的场景。
方案4:使用条件序列化(基于原有Data类改造)
若不想修改原有类结构,可结合JsonIgnore和空值忽略配置,只序列化需要的属性:
using Newtonsoft.Json; public class Data { [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float? water { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float? miscellaneous { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float? transport { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float? salaries { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float? rents { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public float? wages { get; set; } } // 使用示例 var data = new Data { rents = 0.0f, wages = 0.0f }; string json = JsonConvert.SerializeObject( new Rootobject { activity = new Activity { referenceId = "", data = data } }, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore } );
内容的提问来源于stack exchange,提问作者Captain Kenpachi
相关产品推荐
相关产品推荐

