C#单模型序列化时如何不新增类生成嵌套结构JSON
解决方案
以下方案基于你使用的Newtonsoft.Json(Json.NET)实现,全程不需要创建额外的嵌套类:
方案1:自定义JsonConverter(可复用,推荐)
适合需要多次对该类/同类规则的模型做序列化的场景,仅需一次开发,后续直接加特性即可使用。
首先实现自定义Converter:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Reflection; public class DotSeparatedPropertyConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { JObject result = new JObject(); PropertyInfo[] properties = value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo prop in properties) { // 读取JsonProperty配置的属性名 JsonPropertyAttribute jsonAttr = prop.GetCustomAttribute<JsonPropertyAttribute>(); string jsonKey = jsonAttr?.PropertyName ?? prop.Name; object propValue = prop.GetValue(value); if (!jsonKey.Contains('.')) { // 普通属性直接赋值 result[jsonKey] = JToken.FromObject(propValue, serializer); continue; } // 拆分带点的属性名,生成嵌套结构 string[] keySegments = jsonKey.Split('.'); JObject currentNode = result; for (int i = 0; i < keySegments.Length - 1; i++) { string segment = keySegments[i]; if (currentNode[segment] == null) { currentNode[segment] = new JObject(); } currentNode = (JObject)currentNode[segment]; } currentNode[keySegments.Last()] = JToken.FromObject(propValue, serializer); } result.WriteTo(writer); } // 不需要反序列化的话可以直接返回false public override bool CanRead => false; public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } public override bool CanConvert(Type objectType) { // 可根据需求修改要适配的类型,返回true则全局生效 return objectType == typeof(ApiRequest); } }
然后给你的模型类加Converter特性即可(注意修正你原代码里JsonProperty的拼写错误:PropertName→PropertyName):
[JsonConverter(typeof(DotSeparatedPropertyConverter))] public class ApiRequest{ [JsonProperty(PropertyName="name")] public string Name{get;set;} [JsonProperty(PropertyName="description")] public string Description{get;set;} [JsonProperty(PropertyName="privacy.view")] public string PrivacyStats {get;set;} }
直接正常序列化就能得到目标结构:
var req = new ApiRequest { Name = "Test1", Description = "Testing Only", PrivacyStats = "unlisted" }; // 输出就是你需要的嵌套JSON string json = JsonConvert.SerializeObject(req, Formatting.Indented);
方案2:JObject手动处理(一次性场景快速实现)
如果只需要偶尔处理一次序列化,不需要复用逻辑,可以直接操作JObject实现,不用修改原有模型,也不用写Converter:
var req = new ApiRequest { Name = "Test1", Description = "Testing Only", PrivacyStats = "unlisted" }; // 先把对象转成JObject JObject jObj = JObject.FromObject(req); // 取出带点的属性值,删除原属性 string viewValue = jObj.Value<string>("privacy.view"); jObj.Remove("privacy.view"); // 添加嵌套结构 jObj["privacy"] = new JObject { ["view"] = viewValue }; // 得到最终JSON string json = jObj.ToString(Formatting.Indented);
内容的提问来源于stack exchange,提问作者JPil
相关产品推荐
相关产品推荐

