.NET 4.8下用System.Text.Json序列化JSON时如何添加注释?
在System.Text.Json中为JSON序列化添加字段注释(.NET 4.8 + v9.0)
你提到的Newtonsoft.Json自定义转换器传参的方案,在System.Text.Json中行不通,因为它的JsonConverterAttribute不支持通过属性参数向转换器传递值。要实现值后追加/*注释内容*/的序列化效果,可以按以下步骤实现:
1. 定义注释属性
先创建一个自定义属性,用来标记每个字段的注释内容:
[AttributeUsage(AttributeTargets.Property)] public class JsonPropertyCommentAttribute : Attribute { public string Comment { get; } public JsonPropertyCommentAttribute(string comment) { Comment = comment; } }
2. 自定义JSON写入器
继承Utf8JsonWriter,重写值写入方法,在写完值后追加注释:
public class CommentJsonWriter : Utf8JsonWriter { private string _currentPropertyComment; public CommentJsonWriter(Stream stream, JsonWriterOptions options) : base(stream, options) { } public void SetCurrentPropertyComment(string comment) { _currentPropertyComment = comment; } public override void WriteStringValue(string value) { base.WriteStringValue(value); AppendComment(); } public override void WriteNumberValue(int value) { base.WriteNumberValue(value); AppendComment(); } // 按需重写其他值类型的Write方法,比如long、bool、double等 public override void WriteNumberValue(long value) { base.WriteNumberValue(value); AppendComment(); } public override void WriteBooleanValue(bool value) { base.WriteBooleanValue(value); AppendComment(); } private void AppendComment() { if (!string.IsNullOrWhiteSpace(_currentPropertyComment)) { WriteRawValue($"/*{_currentPropertyComment}*/"); _currentPropertyComment = null; } } }
3. 实现通用实体转换器
创建一个通用转换器,通过反射读取属性上的注释,配合自定义写入器完成序列化:
public class CommentConverter<T> : JsonConverter<T> where T : class, new() { public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 反序列化时忽略注释,使用默认逻辑 options.ReadCommentHandling = JsonCommentHandling.Skip; return JsonSerializer.Deserialize<T>(ref reader, options); } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { var commentWriter = writer as CommentJsonWriter; if (commentWriter == null) { JsonSerializer.Serialize(writer, value, options); return; } commentWriter.WriteStartObject(); var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var prop in properties) { var commentAttr = prop.GetCustomAttribute<JsonPropertyCommentAttribute>(); var propValue = prop.GetValue(value); commentWriter.WritePropertyName(prop.Name); commentWriter.SetCurrentPropertyComment(commentAttr?.Comment); // 根据属性类型写入值,这里可以扩展更多类型 if (prop.PropertyType == typeof(string)) { commentWriter.WriteStringValue(propValue as string); } else if (prop.PropertyType == typeof(int)) { commentWriter.WriteNumberValue((int)propValue); } else if (prop.PropertyType == typeof(long)) { commentWriter.WriteNumberValue((long)propValue); } else if (prop.PropertyType == typeof(bool)) { commentWriter.WriteBooleanValue((bool)propValue); } // 其他类型可自行扩展 } commentWriter.WriteEndObject(); } }
4. 标记实体类属性
用自定义注释属性标记需要添加注释的字段:
public class Person { [JsonPropertyComment("Name of the person")] public string Name { get; set; } [JsonPropertyComment("Age of the person")] public int Age { get; set; } }
5. 序列化调用示例
var person = new Person { Name = "Jack", Age = 22 }; using var stream = new MemoryStream(); var writerOptions = new JsonWriterOptions { Indented = true }; using var commentWriter = new CommentJsonWriter(stream, writerOptions); var serializerOptions = new JsonSerializerOptions(); serializerOptions.Converters.Add(new CommentConverter<Person>()); JsonSerializer.Serialize(commentWriter, person, serializerOptions); stream.Position = 0; using var reader = new StreamReader(stream); var resultJson = reader.ReadToEnd(); Console.WriteLine(resultJson);
注意事项
- 生成的JSON包含注释,不符合JSON标准,反序列化时需设置
JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip来忽略注释 - 通用转换器目前只实现了常见类型,可根据实际需求扩展更多数据类型的写入逻辑
- 如果需要支持嵌套实体,需在转换器中递归处理嵌套属性
内容的提问来源于stack exchange,提问作者user1797147
相关产品推荐
相关产品推荐

