如何让Newtonsoft.Json仅序列化字段而非属性(不修改类库)
解决定点数库对象仅序列化指定字段且避免循环引用的方案
针对你不能修改定点数库源码、仅需序列化x/y字段并解决循环引用的需求,以下是两种主流JSON序列化库的实现方案:
Newtonsoft.Json(Json.NET)方案
通过自定义ContractResolver过滤要序列化的成员,完全无需修改库文件:
public class FixedPointContractResolver : DefaultContractResolver { protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { // 仅保留公共实例字段中的x和y return type.GetFields(BindingFlags.Public | BindingFlags.Instance) .Where(field => field.Name is "x" or "y") .Select(field => CreateProperty(field, memberSerialization)) .ToList(); } }
使用时配置序列化设置:
var serializerSettings = new JsonSerializerSettings { ContractResolver = new FixedPointContractResolver(), // 额外开启循环引用忽略,防止漏网的引用问题 ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; string serializedJson = JsonConvert.SerializeObject(yourFixedPointInstance, serializerSettings);
System.Text.Json 方案
通过自定义JsonConverter精确控制序列化内容:
public class FixedPointConverter : JsonConverter<YourFixedPointType> { public override YourFixedPointType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 实现反序列化逻辑,按需读取x和y字段 using var jsonDoc = JsonDocument.ParseValue(ref reader); var root = jsonDoc.RootElement; var instance = new YourFixedPointType(); if (root.TryGetProperty("x", out var xElement)) instance.x = JsonSerializer.Deserialize<fp>(xElement.GetRawText(), options); if (root.TryGetProperty("y", out var yElement)) instance.y = JsonSerializer.Deserialize<fp>(yElement.GetRawText(), options); return instance; } public override void Write(Utf8JsonWriter writer, YourFixedPointType value, JsonSerializerOptions options) { // 仅序列化x和y字段 writer.WriteStartObject(); writer.WritePropertyName("x"); JsonSerializer.Serialize(writer, value.x, options); writer.WritePropertyName("y"); JsonSerializer.Serialize(writer, value.y, options); writer.WriteEndObject(); } }
配置并使用序列化器:
var serializerOptions = new JsonSerializerOptions(); serializerOptions.Converters.Add(new FixedPointConverter()); // 开启循环引用忽略增强容错性 serializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; string serializedJson = JsonSerializer.Serialize(yourFixedPointInstance, serializerOptions);
注意事项
- 两种方案均无需修改定点数库源码,后续库版本更新不会影响配置逻辑
- 循环引用忽略配置作为额外保障,配合字段过滤可彻底解决之前的序列化错误
内容的提问来源于stack exchange,提问作者frostymm
相关产品推荐
相关产品推荐

