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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:06:05