2016-10-02 5 views
2

私はJson.NET用のカスタムValueProviderを作成しようとしています。これはすべてのオブジェクトのシリアル化をスキップし、代わりに主キーを表すGuid型のプロパティを返します参照)。オブジェクトをGuidに変換するためのJson.NETカスタムValueProvider

例:

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 
    }; 

答えて

3

"Id"の値をネストしたオブジェクトの内部から親オブジェクトに昇格させたいとします。これを行うには、2つのバリュープロバイダーを連鎖させる必要があります。

  • メンバーの値を取得する外部値プロバイダー。
  • メンバの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>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; } 
} 
+1

うーん...私は、これは非常に困難であることを期待していませんでした。ありがとう、あなたは私を救った。 – tocqueville

関連する問題