2011-11-14 16 views
4

我正在嘗試生成將在Dojo javascript框架內使用的JSON文件,並且想要返回要在dojo.place()中使用的position屬性呼叫。 position參數可以是或者的一個數字或字符串。如何使用Json.NET序列化C#中的「union-like」字段

使用StructLayout似乎不工作,因爲串行器會嘗試發出字符串和整數類型。我正在創建一個自定義ContractResolver,它將覆蓋CreatePrimitiveContract以返回自定義類JsonConverter。但是,查看API時,看起來JsonConverter是基於類型創建的,而不是特定的對象值。

如何在C#中使用Json.NET序列化程序處理這種情況?

假設解決方案將涉及兩個屬性與自定義設置器,以清空其他屬性,當一個設置與某種自定義Json.Net類聯合檢查屬性的值,並只序列化非空值。

**假設的例子**

// C# struct (or class) 
[StructLayout(LayoutKind.Explicit)] 
struct DojoPosition { 
    [JsonProperty(PropertyName="position")] 
    [FieldOffset(0)] 
    public String StrPos; 

    [JsonProperty(PropertyName="position")] 
    [FieldOffset(0)] 
    public Int32 IntPos; 
} 

// Serialization output 
DojoPosition pos; 
pos.StrPos = "only"; 
var output = JsonConvert.SerializeObject(pos); 

// Output is: { "position": "only" } 

pos.IntPos = 3; 
var output = JsonConvert.SerializeObject(pos); 

// Output is: { "position": 3 } 

回答

1

我剛剛有了一個類似的問題。 對於簡單的合約操作看起來有:Overriding the serialization behaviour in Json.Net

爲了解決JsonPrimitiveContract覆蓋CreateContract方法。

這是基於我們的解決方案的例子:

public class JsonDotNetContractResolver : DefaultContractResolver 
    { 
     protected override JsonContract CreateContract(Type objectType) 
     { 
     if (typeof(DojoPosition).IsAssignableFrom(objectType)) 
     { 
      return new JsonPrimitiveContract(objectType.GetGenericArguments()[1]) 
         { 
         CreatedType = typeof(object), // Not sure this will work for you, or is necessary... 
         IsReference = false, 
         Converter = DojoPositionConverter, 
         }; 
     } 
     return base.CreateContract(objectType); 
     } 
     private class DojoPositionConverter : JsonConverter 
     { 
     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      var dp = (DojoPosition) value; 
      if(string.IsNullOrEmpty(dp.StrPos)) 
       serializer.Serialize(writer,dp.IntPos); 
      else 
       serializer.Serialize(writer,dp.StrPos); 
     } 
     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
     { 
      //... 
     } 
     public override bool CanConvert(Type objectType) 
     { 
      //.... 
     } 
     }  
    } 

如何確定從閱讀器反序列化的類型是你的功課;)

+0

完美!我錯過了通過CreateContract方法的連接。這讓我走上了正軌。 – Lucas

+0

Json.Net已被記錄,但入口點很難找到... – sanosdole