无需令牌选择器,如何用对象值自动部分替换JSON属性
问题描述
给定如下C#模型:
public class Fruit { public int Id { get; set; } public string FruitName { get; set; } }
以及如下JSON字符串:
{ "Id": 1, "FruitName": "Apple", "Currency": "USD" }
要求不使用令牌选择器,通过编程方式替换JSON中Id和FruitName的属性值,同时保留Currency这类模型中不存在的属性。
已知可以通过逐个赋值实现:
FruitJson["Id"] = Fruit.Id; FruitJson["FruitName"] = Fruit.FruitName;
但希望基于已有Fruit对象实现更通用的方案,比如类似以下逻辑:
dynamic fruitJson = JObject.Parse(json); Fruit fruit = new Fruit { Id = 1, FruitName = "Orange" }; fruitJson.ReplaceOnlyPropertiesThatExistInObject(fruit);
执行后期望输出:
{ "Id": 1, "FruitName": "Orange", "Currency": "USD" }
尝试过的方法都会误删Currency属性,已知JsonSerializer.Populate可以用JSON填充对象,但需要反向操作(用对象更新JSON,保留额外属性)。
解决方案
方案一:反射遍历属性更新JObject
通过反射获取目标对象的所有公共属性,遍历后更新JObject中对应的键,完全保留JSON原有额外属性。
代码实现:
using Newtonsoft.Json.Linq; using System.Reflection; // 解析原始JSON字符串 JObject fruitJson = JObject.Parse(json); // 待更新的Fruit实例 Fruit fruit = new Fruit { Id = 1, FruitName = "Orange" }; // 获取Fruit类型的所有公共实例属性 PropertyInfo[] properties = typeof(Fruit).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo prop in properties) { // 获取对象的属性值 object propValue = prop.GetValue(fruit); // 检查JObject中是否存在对应键,存在则更新值 if (fruitJson.ContainsKey(prop.Name)) { fruitJson[prop.Name] = JToken.FromObject(propValue); } } // 输出更新后的JSON string updatedJson = fruitJson.ToString();
方案二:封装为JObject扩展方法
如果需要重复使用该逻辑,可封装成扩展方法,实现需求中设想的ReplaceOnlyPropertiesThatExistInObject调用方式:
using Newtonsoft.Json.Linq; using System.Reflection; public static class JObjectExtensions { public static void ReplaceOnlyPropertiesThatExistInObject<T>(this JObject jObject, T sourceObject) { if (sourceObject == null) throw new ArgumentNullException(nameof(sourceObject)); PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo prop in properties) { object propValue = prop.GetValue(sourceObject); if (jObject.ContainsKey(prop.Name)) { jObject[prop.Name] = JToken.FromObject(propValue); } } } }
调用方式:
dynamic fruitJson = JObject.Parse(json); Fruit fruit = new Fruit { Id = 1, FruitName = "Orange" }; fruitJson.ReplaceOnlyPropertiesThatExistInObject(fruit);
补充说明
- 以上代码依赖Newtonsoft.Json(Json.NET)库;若使用System.Text.Json,可通过
JsonNode实现类似逻辑,遍历对象属性后更新对应节点值。 - 反射方式具备通用性,后续
Fruit类新增属性时,无需修改更新逻辑,会自动同步JSON中对应键的值。
内容的提问来源于stack exchange,提问作者Hydromast
相关产品推荐
相关产品推荐

