Json.NET Custom ValueProvider将对象转换为Guid
我正在尝试为Json.NET创建一个自定义ValueProvider,它将跳过序列化所有对象,并且只返回表示其主键的Guid类型的属性(作为参考)。
例:
jsonData: { myObject: { id: "23e23-2gg5-6y666556-y6yg33", property2: "" } }
应该成为:
jsonData: { myObjectId: "23e23-2gg5-6y666556-y6yg33" }
这是我到目前为止编写的代码。 我非常接近使它工作,但在我的CustomValueProvider
我似乎无法获得对象值。 我怎样才能做到这一点?
private class CustomValueProvider : IValueProvider { private readonly MemberInfo _member; public CustomValueProvider(MemberInfo member) { _member = member; } public void SetValue(object target, object value) { throw new NotImplementedException(); } public object GetValue(object target) { return // WHAT HERE?? } } private class CustomResolver : CamelCasePropertyNamesContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var jsonProperty = base.CreateProperty(member, memberSerialization); if (jsonProperty.PropertyType.IsClass && jsonProperty.PropertyType != typeof(string)) { jsonProperty = new JsonProperty { PropertyName = member.Name.ToFirstCharLower() + "Id", Readable = true, ShouldSerialize = value => true, PropertyType = typeof(Guid), ValueProvider = new CustomValueProvider(member) }; } return jsonProperty; } } private static readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings { ContractResolver = new CustomResolver(), Formatting = Formatting.Indented };
您希望将嵌套对象内的"Id"
值提升为父对象。 要做到这一点,您需要将两个价值提供者联系在一起:
- 用于获取成员值的外部值提供程序。
- 内部值提供程序,用于获取成员
Id
的值。
以下是这样的:
class NestedValueProvider : IValueProvider { readonly IValueProvider outerProvider; readonly IValueProvider innerProvider; public NestedValueProvider(IValueProvider outerProvider, IValueProvider innerProvider) { if (outerProvider == null || innerProvider == null) throw new ArgumentNullException(); this.outerProvider = outerProvider; this.innerProvider = innerProvider; } public void SetValue(object target, object value) { throw new NotImplementedException(); } public object GetValue(object target) { var innerTarget = outerProvider.GetValue(target); if (innerTarget == null) return null; return innerProvider.GetValue(innerTarget); } } class CustomResolver : CamelCasePropertyNamesContractResolver { // Using an inner resolver prevents difficulties with recursion. readonly CamelCasePropertyNamesContractResolver innerResolver = new CamelCasePropertyNamesContractResolver(); protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var jsonProperty = base.CreateProperty(member, memberSerialization); if (!jsonProperty.PropertyType.IsPrimitive && jsonProperty.PropertyType != typeof(string) && jsonProperty.Readable) { var innerContract = innerResolver.ResolveContract(jsonProperty.PropertyType); if (innerContract is JsonObjectContract) { var objectContract = (JsonObjectContract)innerContract; var idProperty = objectContract.Properties.GetClosestMatchProperty(ResolvePropertyName("Id")); if (idProperty != null && idProperty.Readable && (innerResolver.ResolveContract(idProperty.PropertyType) is JsonPrimitiveContract)) { jsonProperty = new JsonProperty { PropertyName = ResolvePropertyName(member.Name + "Id"), Readable = true, PropertyType = idProperty.PropertyType, ValueProvider = new NestedValueProvider(jsonProperty.ValueProvider, idProperty.ValueProvider), }; } } // Possibly handle innerContract is JsonArrayContract? // Possibly handle innerContract is JsonDictionaryConract? } return jsonProperty; } }
注意使用内部合同解析器。 这可以防止递归调用递归类型的问题。
您可能还需要考虑使用ID处理对象集合,或者使用具有ID的对象字典。 例如,在以下对象中, List
和Dictionary
属性将公开MyObject
内容:
public class RootObject { // Correctly not remapped public string StringValue { get; set; } // Correctly remaps to a GUID. public MyObject MyObject { get; set; } // Remap to a List ? public List MyObjectList { get; set; } // Remap to a Dictionary ? public Dictionary MyObjectDictionary { get; set; } } public class MyObject { public Guid Id { get; set; } public string Property2 { get; set; } }
- JsonConvert.DeserializeObject特殊字符未终止字符串。 预期分隔符:
- Visual Studio 2017,无法调试或运行该应用程序
- ASP.NET MVC OWIN和SignalR – 两个Startup.cs文件
- entity framework5代码首先添加图像
- 在EF6中将匿名类型转换为IEnumerable
- Session.Clear(),Session.Abandon(),Session.RemoveAll()的MVC优化?
- 在Asp.Net MVC中使用JsTree延迟加载TreeView
- 在ASP.NET MVC 2中,我可以使用默认的ModelBinder将查询字符串反序列化为数组吗?
- 数组必须包含1个元素