Json.NET自定义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<MyObject>and

Dictionary<string, MyObject>属性将公开以下内容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<Guid> ?

public List<MyObject> MyObjectList { get; set; }

// Remap to a Dictionary<string, Guid> ?

public Dictionary<string, MyObject> MyObjectDictionary { get; set; }

}

public class MyObject

{

public Guid Id { get; set; }

public string Property2 { get; set; }

}

以上是 Json.NET自定义ValueProvider将对象转换为Guid 的全部内容, 来源链接: utcz.com/qa/408603.html

回到顶部