如何仅用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
相关产品推荐
相关产品推荐

