2013-08-31 56 views
16

我有一個枚舉用C#,在那裏我存儲它的值字符,這樣定義JSON是使用CHAR值(字符串),而不是枚舉的int值寫的,就像這樣:反序列化JSON字符作爲枚舉

[{"CardType","A"},{"CardType", "C"}] 

是否有可能定義某種轉換器的,讓我爲char手動解析到枚舉值?

我試着創建一個JsonConverter,但不知道如何去做,而只將它應用到這個屬性,而不是整個解析對象。這裏是我的嘗試:

public class EnumerationConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     serializer.Serialize(writer, value); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
     { 
      return null; 
     } 

     int value = serializer.Deserialize<int>(reader); 
     return (CardType)value; 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return objectType.IsSubclassOf(typeof(string)); 
    } 
} 

的邏輯可能是錯誤的,我可以解決這個問題,但問題是ReadJson()不會被調用的。

CanConvert是,但它似乎被調用每個屬性,而不僅僅是一個屬性我定義它:

public class Card 
{ 
      private CardType type; 
     [JsonConverter(typeof(EnumerationConverter))] 
     public CardType Type 
     { 
      get { return type; } 
      set { type = value; } 
     } 
} 

我敢肯定,我已經做了這個錯誤,但我無法找到文件關於如何爲單個字段執行此操作...

我錯過了什麼?

+0

您可以發佈具有在deserilization失敗'CardType'屬性的示例類? – nemesv

+0

可以發佈完整的枚舉。我相信你不能聲明enum,因爲你已經定義了 – dharam

+0

以上的類被反序列化成只是有一個CardType屬性來接收反序列化的值,除了聲明之外沒有其他的東西。至於枚舉值,這確實是ENUM的完整定義。 Card類具有用於存儲枚舉類型值的CardType類型的屬性。 – SelAromDotNet

回答

16

你沒必要需要自定義JsonConverter可以使用內置StringEnumConverterEnumMemberAttribute(來自System.Runtime.Serialization組件)的組合。

如果沒有EnumMemberAttribute它使用枚舉名稱Artist,Contemporary等等,所以您需要將它的名稱更改爲您的A,C等值。

但它不是最好的解決方案,因爲你必須重複你的價值的兩倍,但它的工作原理:

[JsonConverter(typeof(StringEnumConverter))] 
public enum CardType 
{ 
    [EnumMember(Value = "A")] 
    Artist = 'A', 
    [EnumMember(Value = "C")] 
    Contemporary = 'C', 
    [EnumMember(Value = "H")] 
    Historical = 'H', 
    [EnumMember(Value = "M")] 
    Musician = 'M', 
    [EnumMember(Value = "S")] 
    Sports = 'S', 
    [EnumMember(Value = "W")] 
    Writer = 'W' 
} 
+0

哇這看起來像一個理想的解決方案,它絕對工作得很好,謝謝! – SelAromDotNet

+1

如何反序列化上面的一個? 我在反序列化這個問題。 例如: Service具有該枚舉: [EnumMember(值= 「當代」)] 當代= 'C', UI代碼具有該枚舉: [EnumMember(值= 「當代」)] 當代=「C ' 因此,雖然反序列化,它無法找到「Contemp」..有沒有辦法做到這一點?或者只是將Enum和Value互換爲, [EnumMember(Value =「ontemporary」)] Contemp ='C', –

3

此代碼的工作完美:

CardType[] array = { CardType.Artist, CardType.Contemporary }; 
string s = JsonConvert.SerializeObject(array); 
var array2 = JsonConvert.DeserializeObject<CardType[]>(s); 

更新
什麼亂盒StringEnumConverter

[JsonConverter(typeof(StringEnumConverter))] 
public CardType Type { get; set; } 
+0

是的,我很抱歉,我錯了,JSON不是由序列化生成的,它是一個自定義的JSON字符串,它使用char值而不是int。請參閱最新的說明,並感謝您的幫助! – SelAromDotNet

0

你可以只添加SerializerSettings.Converters.Add(新StringEnumConverter());

您BrowserJsonFormatter類

public class BrowserJsonFormatter : JsonMediaTypeFormatter 
{ 
    public BrowserJsonFormatter() 
    { 
     SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); 
     SerializerSettings.Formatting = Formatting.Indented; 
     SerializerSettings.NullValueHandling = NullValueHandling.Ignore; 
     SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 
     SerializerSettings.Converters.Add(new EmptyToNullConverter()); 
     SerializerSettings.Converters.Add(new StringEnumConverter()); 
     //SerializerSettings.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate; 
    } 

    public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType) 
    { 
     base.SetDefaultContentHeaders(type, headers, mediaType); 
     headers.ContentType = new MediaTypeHeaderValue("application/json"); 
    } 
}