如何使用Newtonsoft契约解析器重命名并移动序列化对象属性
解决方案
要实现将嵌套属性移至JSON根节点的需求,仅靠自定义ContractResolver无法完成(它仅负责单个类型的属性映射,无法跨层级访问父对象或调整整体结构),推荐使用**自定义JsonConverter<BaseSerializer>**来控制整个序列化流程,以下是具体实现:
1. 自定义Json转换器
创建针对BaseSerializer的转换器,手动构建期望的JSON结构:
public class BaseSerializerConverter : JsonConverter<BaseSerializer> { public override void WriteJson(JsonWriter writer, BaseSerializer? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } writer.WriteStartObject(); // 提取player1Name到根节点 if (value.Players?.Count > 0) { var firstPlayerEntry = value.Players[0]; // 写入根节点的player1Name if (!string.IsNullOrEmpty(firstPlayerEntry.Player1?.Name)) { writer.WritePropertyName("player1Name"); writer.WriteValue(firstPlayerEntry.Player1.Name); } // 写入调整后的players对象(将原数组第一个元素转为对象) writer.WritePropertyName("players"); writer.WriteStartObject(); if (!string.IsNullOrEmpty(firstPlayerEntry.OtherProp)) { writer.WritePropertyName("otherProp"); writer.WriteValue(firstPlayerEntry.OtherProp); } writer.WriteEndObject(); } writer.WriteEndObject(); } public override BaseSerializer? ReadJson(JsonReader reader, Type objectType, BaseSerializer? existingValue, bool hasExistingValue, JsonSerializer serializer) { // 反序列化逻辑保持原有逻辑,适配输入的JSON格式 var jObject = JObject.Load(reader); var baseModel = new BaseSerializer(); baseModel.Players = jObject["players"]?.ToObject<IList<PlayersSerializer>>(serializer); return baseModel; } }
2. 使用转换器进行序列化
在序列化时,将自定义转换器和原有的ContractResolver一起配置到序列化设置中:
var jsonSettings = new JsonSerializerSettings { ContractResolver = MyCustomContractResolver.Instance, Converters = new List<JsonConverter> { new BaseSerializerConverter() }, NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented }; var outputJson = JsonConvert.SerializeObject(test, jsonSettings);
说明
- 转换器通过手动写入JSON节点,实现了将嵌套的
player1.name提取到根节点,同时将原players数组转为单个对象输出的需求。 - 反序列化逻辑保持与原有逻辑一致,确保可以正常解析输入的JSON格式。
- 如果
players数组存在多个元素,可根据需求调整逻辑(如遍历所有元素或处理特定元素)。
内容的提问来源于stack exchange,提问作者Jumbala
相关产品推荐
相关产品推荐

