如何从字符串创建可序列化/反序列化的C# Version对象?
解决C# Version类型Newtonsoft.Json序列化反序列化的负字段问题
直接用自定义JsonConverter来处理Version类型的序列化和反序列化是最优雅的方案,完美适配各种版本字符串格式,同时彻底避免负字段导致的反序列化错误。
方案一:将Version序列化为版本字符串(推荐)
这种方式序列化后的JSON是简洁的版本字符串(比如"6.10.7011"),反序列化时直接解析字符串重建Version对象,完全绕开负字段问题。
自定义转换器代码
public class VersionConverter : JsonConverter<Version> { public override void WriteJson(JsonWriter writer, Version value, JsonSerializer serializer) { // 利用Version.ToString()自动忽略值为-1的部分,输出标准版本字符串 writer.WriteValue(value.ToString()); } public override Version ReadJson(JsonReader reader, Type objectType, Version existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.Value is string versionStr) { return Version.Parse(versionStr); } throw new JsonSerializationException("无法解析无效的版本字符串"); } }
使用方式
方式1:给属性添加特性标记
public class YourModel { [JsonConverter(typeof(VersionConverter))] public Version ProtocolVersion { get; set; } }
方式2:全局配置转换器
var jsonSettings = new JsonSerializerSettings(); jsonSettings.Converters.Add(new VersionConverter()); // 序列化 var json = JsonConvert.SerializeObject(yourModelInstance, jsonSettings); // 反序列化 var model = JsonConvert.DeserializeObject<YourModel>(json, jsonSettings);
方案二:序列化时过滤负数值属性
如果希望序列化后仍是对象格式(而非字符串),可以通过自定义ContractResolver过滤掉值为-1的Build和Revision字段:
自定义ContractResolver代码
public class VersionContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var property = base.CreateProperty(member, memberSerialization); // 过滤值为-1的Build字段 if (member.DeclaringType == typeof(Version) && property.PropertyName == nameof(Version.Build)) { property.ShouldSerialize = instance => ((Version)instance).Build >= 0; } // 过滤值为-1的Revision字段 if (member.DeclaringType == typeof(Version) && property.PropertyName == nameof(Version.Revision)) { property.ShouldSerialize = instance => ((Version)instance).Revision >= 0; } return property; } }
使用方式
var jsonSettings = new JsonSerializerSettings(); jsonSettings.ContractResolver = new VersionContractResolver(); // 序列化后的JSON只会包含非-1的属性,比如Version("6.10.7011")会序列化为{"Major":6,"Minor":10,"Build":7011} var json = JsonConvert.SerializeObject(yourModelInstance, jsonSettings);
两种方案都能解决你的问题,方案一更简洁直观,也更符合版本号的常规表示形式;方案二则保留了对象结构,适合需要结构化版本信息的场景。
内容的提问来源于stack exchange,提问作者komodosp
相关产品推荐
相关产品推荐

