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

如何在Json.NET中基于对象动态属性为属性名添加前缀?

动态属性前缀的Json.NET序列化实现方法

问题场景

需要序列化一个对象,要求根据对象中动态变化的Prefix属性,为其他属性名添加对应前缀。由于Prefix是运行时动态值,无法提前用JsonProperty特性指定。示例代码如下:

public class Example
{
    [JsonIgnore]
    public string Prefix { get; set; }

    public string Name { get; set; }
    public string Value { get; set; }
}

序列化代码:

var fooExample = new Example
{
    Prefix = "foo_",
    Name = "TestName",
    Value = "TestValue"
};

JsonConvert.SerializeObject(fooExample);

期望输出:

{
    "foo_Name": "TestName",
    "foo_Value": "TestValue"
}

尝试过重写ContractResolver的CreateProperty方法,但无法获取父对象实例来读取Prefix值,代码如下:

protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
    JsonProperty property = base.CreateProperty(member, memberSerialization);

    // 无法从这里获取父对象的Prefix值
    string prefix = "";

    property.PropertyName = prefix + property.PropertyName;

    return property;
}

需要找到Json.NET的其他实现方式。

解决方案

方案1:自定义JsonConverter

自定义JsonConverter可直接在序列化过程中访问当前对象实例,从而获取动态的Prefix值,具体实现如下:

public class PrefixPropertyConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Example);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var example = (Example)value;
        var prefix = example.Prefix ?? string.Empty;

        writer.WriteStartObject();

        // 遍历所有非JsonIgnore标记的属性
        var properties = typeof(Example).GetProperties()
            .Where(p => !Attribute.IsDefined(p, typeof(JsonIgnoreAttribute)));

        foreach (var prop in properties)
        {
            var propValue = prop.GetValue(example);
            writer.WritePropertyName(prefix + prop.Name);
            serializer.Serialize(writer, propValue);
        }

        writer.WriteEndObject();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // 如需反序列化,可在此实现对应逻辑,示例暂省略
        throw new NotImplementedException();
    }
}

使用方式:

var settings = new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new PrefixPropertyConverter() }
};

var json = JsonConvert.SerializeObject(fooExample, settings);

方案2:改进ContractResolver结合序列化上下文

若希望复用ContractResolver的逻辑,可通过JsonSerializerSettings的Context属性传递当前对象的前缀,实现如下:

public class PrefixContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        
        if (property.DeclaringType == typeof(Example) && !property.Ignored)
        {
            // 从序列化上下文中获取前缀
            var prefix = JsonSerializer.Current.Context.Context as string;
            if (!string.IsNullOrEmpty(prefix))
            {
                property.PropertyName = prefix + property.PropertyName;
            }
        }
        
        return property;
    }
}

使用时传递上下文:

var settings = new JsonSerializerSettings
{
    ContractResolver = new PrefixContractResolver(),
    Context = new StreamingContext(StreamingContextStates.All, fooExample.Prefix)
};

var json = JsonConvert.SerializeObject(fooExample, settings);

此方式需注意上下文传递的正确性,逻辑相对自定义Converter稍复杂。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 21:48:08