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

如何仅用Json.Net公共API高效实现类的字符串表示直接写入?

问题描述

我有一个带ToString()方法的类,之前靠这个方法自定义Json.Net序列化,把类序列化为ToString()返回的字符串,但序列化数十万对象时会产生大量短生命周期字符串,给GC带来额外压力。

我希望直接向JsonWriter写入内容,模拟ToString()的逻辑,比如定义了包含Write()方法的类X:

class X
{
    public override string ToString(){ ... }
    public void Write(JsonWriter writer){ ... }
}

需要自定义Json序列化器来调用X.Write()方法,但不知道怎么实现才能让它遵守配置的格式化及其他Json设置。目前只能通过反射实现:

private static readonly Action<JsonWriter, JsonToken> s_internalWriteValue = (Action<JsonWriter, JsonToken>)Delegate
    .CreateDelegate(typeof(Action<JsonWriter, JsonToken>), typeof(JsonWriter)
    .GetMethod("InternalWriteValue", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic));

...

internal void Write(JsonWriter writer)
{
...
    s_internalWriteValue(writer, JsonToken.String);
    writer.WriteRaw("\"[");
    writer.WriteRaw(statusCode);
    writer.WriteRaw(",");
    writer.WriteRaw(isCompilerGeneratedCode);
    writer.WriteRaw(",");
    writer.WriteRaw(scope);
    writer.WriteRaw(",");
    writer.WriteRaw(kind);
    writer.WriteRaw(",");
    writer.WriteRaw(rawName);
    writer.WriteRaw("] ");
    writer.WriteRaw(Signature);
    writer.WriteRaw("\"");
}

我使用的是Json.Net 13.0.3,没找到仅用公共API的解决方案,请问该如何实现?

解决方案(基于Json.Net公共API)

无需依赖反射调用私有方法,通过自定义JsonConverter即可实现,同时完全遵守Json.Net的配置规则(如格式化、字符串转义、缩进等),具体步骤如下:

1. 实现针对X类的自定义转换器

创建转换器类,在WriteJson方法中直接操作JsonWriter,利用公共API处理转义与格式:

public class XConverter : JsonConverter<X>
{
    public override void WriteJson(JsonWriter writer, X value, JsonSerializer serializer)
    {
        // 开启字符串写入,自动处理首尾引号
        writer.WriteStartString();
        
        // 写入固定前缀(无特殊字符可直接用WriteRaw)
        writer.WriteRaw("[");
        
        // 逐个写入内容,用WriteValue自动处理转义
        writer.WriteValue(value.StatusCode.ToString());
        writer.WriteRaw(",");
        writer.WriteValue(value.IsCompilerGeneratedCode.ToString());
        writer.WriteRaw(",");
        writer.WriteValue(value.Scope);
        writer.WriteRaw(",");
        writer.WriteValue(value.Kind);
        writer.WriteRaw(",");
        writer.WriteValue(value.RawName);
        writer.WriteRaw("] ");
        writer.WriteValue(value.Signature);
        
        // 结束字符串写入
        writer.WriteEndString();
    }

    public override X ReadJson(JsonReader reader, Type objectType, X existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        // 按需实现反序列化逻辑,若不需要可抛出NotImplementedException
        throw new NotImplementedException();
    }
}

2. 注册并使用转换器

有两种方式可以让Json.Net识别这个转换器:

方式一:全局配置注册

var settings = new JsonSerializerSettings();
settings.Converters.Add(new XConverter());

// 序列化对象列表
string json = JsonConvert.SerializeObject(largeListOfX, settings);

方式二:类特性标记

直接在X类上添加特性,无需全局配置:

[JsonConverter(typeof(XConverter))]
class X
{
    // 类成员及原有方法
}

方案优势

  • 无反射依赖:完全使用Json.Net公共API,避免私有方法调用带来的兼容性问题。
  • 遵守配置规则:WriteStartString/WriteEndString自动处理引号,WriteValue会根据序列化配置(如StringEscapeHandling)自动转义特殊字符,保证JSON合法性。
  • 降低GC压力:分段写入避免了创建完整的中间字符串,减少短生命周期对象的产生。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 20:57:07