如何在JSON属性前添加注释?基于.NET特性实现配置文件注释输出
问题描述
我希望将JSON作为程序配置文件格式,写入磁盘时要包含每个字段的描述注释,且尽量通过特性来控制这些注释。现有C#类定义如下:
public class Person { [JsonComment("Name of the person")] public string Name { get; set; } [JsonComment("Age of the person")] public int Age { get; set; } }
期望输出的JSON格式如下:
{ /*Name of the person*/ "Name": "Jack", /*Age of the person*/ "Age": 22 }
此前相关问题大多介绍如何在值后添加注释(例如在"Jack"后),而我需要在属性名前添加注释(例如在"Name"前)。请问使用Json.NET、System.Text.Json或其他库能否实现这种注释格式?
解决方案
使用Json.NET(Newtonsoft.Json)实现
Json.NET本身不直接支持属性前置注释,但可以通过重写JsonTextWriter来精准控制注释输出位置:
- 先定义自定义特性(如果未定义):
public class JsonCommentAttribute : Attribute { public string Comment { get; } public JsonCommentAttribute(string comment) { Comment = comment; } }
- 重写
JsonTextWriter,在写入属性名前检查特性并输出注释:
public class CommentedJsonTextWriter : JsonTextWriter { private readonly Type _targetType; public CommentedJsonTextWriter(TextWriter writer, Type targetType) : base(writer) { _targetType = targetType; Formatting = Formatting.Indented; } public override void WritePropertyName(string name) { var property = _targetType.GetProperty(name); if (property != null) { var commentAttr = property.GetCustomAttribute<JsonCommentAttribute>(); if (commentAttr != null) { WriteIndent(); WriteRaw($"/*{commentAttr.Comment}*/"); WriteNewLine(); } } base.WritePropertyName(name); } }
- 序列化时使用自定义写入器:
var person = new Person { Name = "Jack", Age = 22 }; using var stringWriter = new StringWriter(); using var writer = new CommentedJsonTextWriter(stringWriter, typeof(Person)); new JsonSerializer().Serialize(writer, person); var json = stringWriter.ToString();
使用System.Text.Json实现
System.Text.Json默认也不支持前置注释,可通过自定义JsonConverter实现:
同样先定义
JsonCommentAttribute(代码同Json.NET部分)。创建自定义对象转换器:
public class CommentedObjectConverter<T> : JsonConverter<T> { public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return JsonSerializer.Deserialize<T>(ref reader, options); } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { writer.WriteStartObject(); var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var prop in properties) { var commentAttr = prop.GetCustomAttribute<JsonCommentAttribute>(); if (commentAttr != null) { // 输出/* */格式注释,需手动处理缩进换行 writer.WriteRawValue($"/*{commentAttr.Comment}*/"); writer.WriteRawValue(Environment.NewLine); } var propValue = prop.GetValue(value); writer.WritePropertyName(prop.Name); JsonSerializer.Serialize(writer, propValue, prop.PropertyType, options); } writer.WriteEndObject(); } }
- 配置转换器并序列化:
var options = new JsonSerializerOptions { WriteIndented = true, Converters = { new CommentedObjectConverter<Person>() } }; var json = JsonSerializer.Serialize(new Person { Name = "Jack", Age = 22 }, options);
其他可选方案
- 小众库如
JsonFx支持自定义注释输出,但生态成熟度远不如Json.NET和System.Text.Json; - 若需结合JSON Schema生成注释,可使用
JsonSchema.Net.Generation,但仅用于配置文件生成的话会显得冗余。
内容的提问来源于stack exchange,提问作者vazgriz
相关产品推荐
相关产品推荐

