2017-06-15 5 views
2

私はタイプobjectのプロパティを持っていて、そのタイプに応じて名前を変更する必要があります。 XMLの [XmlElement("PropertyName", typeof(PropertyType))]属性にかなり似ているはずです。Json.netでシリアライズするときの型に応じてプロパティ名を変更する方法は?

例えば、私は、実行時に私の財産はVehicleのタイプを持つプロパティpublic object Item { get; set; }

場合、私は私の財産に「車両」の名前を変更したい持っています。 Profileのタイプの場合は、プロパティの名前を「プロファイル」に変更します。

+2

あなたは[MCVE]にあなたの質問を広げてくださいすることができ作成したいJSONとシリアライズするタイプを表示しますか? See [ask]。この情報だけで、私たちはあなたの問題が何かを推測しています。 – dbc

+0

Json.Net == Newtonsoft.Json - **または** –

+0

はありますか?[JsonPropertyAttribute](http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonPropertyAttribute.htm)をお探しですか? –

答えて

5

ランタイムタイプに基づいてプロパティの名前を動的に変更する組み込みの方法はありませんが、カスタムクラスと組み合わせてカスタムJsonConverterを作成して、必要な処理を行うことができます。 JSONに書き込まれたプロパティの名前を制御できるように、コンバーターをクラスレベルで動作させる必要があります。リフレクションを使用してターゲットクラスのプロパティを繰り返し処理し、objectとして宣言されたプロパティにカスタム属性が適用されているかどうかを確認できます。それが実行され、オブジェクトのランタイム・タイプが属性で指定されたタイプと一致する場合は、属性からプロパティー名を使用します。それ以外の場合は、元のプロパティー名を使用します。 、

public class DynamicPropertyNameConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     Type type = value.GetType(); 
     JObject jo = new JObject(); 

     foreach (PropertyInfo prop in type.GetProperties().Where(p => p.CanRead)) 
     { 
      string propName = prop.Name; 
      object propValue = prop.GetValue(value, null); 
      JToken token = (propValue != null) ? JToken.FromObject(propValue, serializer) : JValue.CreateNull(); 

      if (propValue != null && prop.PropertyType == typeof(object)) 
      { 
       JsonPropertyNameByTypeAttribute att = prop.GetCustomAttributes<JsonPropertyNameByTypeAttribute>() 
        .FirstOrDefault(a => a.ObjectType.IsAssignableFrom(propValue.GetType())); 

       if (att != null) 
        propName = att.PropertyName; 
      } 

      jo.Add(propName, token); 
     } 

     jo.WriteTo(writer); 
    } 

    public override bool CanRead 
    { 
     get { return false; } 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     // ReadJson is not called if CanRead returns false. 
     throw new NotImplementedException(); 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     // CanConvert is not called if a [JsonConverter] attribute is used 
     return false; 
    } 
} 

コンバータを使用する最初のターゲットクラスに[JsonConverter]属性を追加します。

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] 
class JsonPropertyNameByTypeAttribute : Attribute 
{ 
    public string PropertyName { get; set; } 
    public Type ObjectType { get; set; } 

    public JsonPropertyNameByTypeAttribute(string propertyName, Type objectType) 
    { 
     PropertyName = propertyName; 
     ObjectType = objectType; 
    } 
} 

そしてここで、コンバータのコードです:

はここでカスタム属性は、次のようになります動的に名前を付けたいプロパティ(または複数のプロパティ)が含まれています。次に、そのクラスのターゲットプロパティ(またはプロパティ)にカスタム属性を追加します。必要な範囲の属性を追加して、期待している種類の範囲をカバーすることができます。例えば

その後
[JsonConverter(typeof(DynamicPropertyNameConverter))] 
class Foo 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    [JsonPropertyNameByType("Vehicle", typeof(Vehicle))] 
    [JsonPropertyNameByType("Profile", typeof(Profile))] 
    public object Item { get; set; } 
} 

、通常どおりにシリアライズ:ここ

string json = JsonConvert.SerializeObject(foo, Formatting.Indented); 

は、作業のデモです:https://dotnetfiddle.net/75HwrV

関連する問題