2011-06-19 41 views
31

我使用JSON.NET序列化我的一些對象,我想知道是否有一種簡單的方法來覆蓋默認的json.net轉換器僅適用於特定對象?在JSON.NET中的特定對象的自定義轉換

目前,我有以下類:

public class ChannelContext : IDataContext 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public IEnumerable<INewsItem> Items { get; set; } 
} 

JSON.NET目前連載以上,如:

{ 
    "Id": 2, 
    "Name": "name value", 
    "Items": [ item_data_here ] 
} 

是否有可能只是針對特定類這種方式格式而不是:

"Id_2": 
{ 
    "Name": "name value", 
    "Items": [ item data here ] 
} 

我有點新JSON.NET ..我想知道如果上述有東西給d o編寫一個自定義轉換器。我無法找到關於如何寫一個的具體示例,如果任何人都可以指出我的具體來源,我會非常感激。

我需要找到一個解決方案,使特定的類總是轉換相同的,因爲上述上下文是JSON.NET默認轉換器轉換的更大上下文的一部分。

希望我的問題是不夠清楚......

UPDATE:

我已經找到了如何創建新的自定義轉換器(通過創建一個新的類,從JsonConverter繼承並重寫它的抽象方法),我重寫了WriteJson方法如下:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     ChannelContext contextObj = value as ChannelContext; 

     writer.WriteStartObject(); 
     writer.WritePropertyName("id_" + contextObj.Id); 
     writer.WriteStartObject(); 
     writer.WritePropertyName("Name"); 
     serializer.Serialize(writer, contextObj.Name); 

     writer.WritePropertyName("Items"); 
     serializer.Serialize(writer, contextObj.Items); 
     writer.WriteEndObject(); 
     writer.WriteEndObject(); 
    } 

這確實成功地做這項工作,但是...... 我好奇,如果有序列化的R A方式通過重用默認的JsonSerializer(或轉換器)來代替使​​用jsonwriter方法手動「編寫」對象的對象屬性的est。

更新2: 我試圖得到一個更通用的解決方案,並提出了以下幾點:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     writer.WriteStartObject(); 

     // Write associative array field name 
     writer.WritePropertyName(m_FieldNameResolver.ResolveFieldName(value)); 

     // Remove this converter from serializer converters collection 
     serializer.Converters.Remove(this); 

     // Serialize the object data using the rest of the converters 
     serializer.Serialize(writer, value); 

     writer.WriteEndObject(); 
    } 

手動添加轉換器時,串行,這樣也能正常工作:

jsonSerializer.Converters.Add(new AssociativeArraysConverter<DefaultFieldNameResolver>()); 
jsonSerializer.Serialize(writer, channelContextObj); 

但使用[JsonConverter()]時不工作屬性設置到ChannelContext類上述我的自定義coverter因爲執行當發生自參考循環的:

serializer.Serialize(writer, value) 

這顯然是因爲我的自定義轉換器目前被認爲是類的默認轉換器一旦設置與JsonConverterAttribute,所以我得到一個inifinite循環。 爲了解決這個問題,我唯一能想到的就是繼承自一個基本的jsonconverter類,然後調用base.serialize()方法... 但是這樣的JsonConverter類是否存在?

非常感謝!

米奇

+0

1爲尋找解決方案。 –

回答

28

如果任何人的興趣在我的解決方案:

當序列化某些藏品,我想創造一個關聯JSON數組,而不是一個標準的JSON數組,所以我的同事客戶端開發人員可以達到這些領域有效地,使用他們的名字(或關鍵的事情),而不是遍歷它們。

考慮以下幾點:

public class ResponseContext 
{ 
    private List<ChannelContext> m_Channels; 

    public ResponseContext() 
    { 
     m_Channels = new List<ChannelContext>(); 
    } 

    public HeaderContext Header { get; set; } 

    [JsonConverter(
     typeof(AssociativeArraysConverter<ChannelContextFieldNameResolver>))] 
    public List<ChannelContext> Channels 
    { 
     get { return m_Channels; } 
    } 

} 

[JsonObject(MemberSerialization = MemberSerialization.OptOut)] 
public class ChannelContext : IDataContext 
{ 
    [JsonIgnore] 
    public int Id { get; set; } 

    [JsonIgnore] 
    public string NominalId { get; set; } 

    public string Name { get; set; } 

    public IEnumerable<Item> Items { get; set; } 
} 

響應上下文包含被寫入返回給客戶端,就像你可以看到整個響應,它包含了一個叫做「渠道」部分,而不是輸出channelcontexts一個正常的數組,我想能夠輸出方式如下:

"Channels" 
{ 
"channelNominalId1": 
{ 
    "Name": "name value1" 
    "Items": [ item data here ] 
}, 
"channelNominalId2": 
{ 
    "Name": "name value2" 
    "Items": [ item data here ] 
} 
} 

因爲我想用上述的其他情況下爲好,我可能會決定使用不同的屬性作爲他們的「關鍵「,或者甚至可能選擇創建自己的唯一的名稱,它不具有任何財產做什麼,我需要某種通用的解決方案,因此,我編寫了一個名爲AssociativeArraysConverter一個通用類,它繼承JsonConverter以下列方式:

public class AssociativeArraysConverter<T> : JsonConverter 
    where T : IAssociateFieldNameResolver, new() 
{ 
    private T m_FieldNameResolver; 

    public AssociativeArraysConverter() 
    { 
     m_FieldNameResolver = new T(); 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return typeof(IEnumerable).IsAssignableFrom(objectType) && 
       !typeof(string).IsAssignableFrom(objectType); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     IEnumerable collectionObj = value as IEnumerable; 

     writer.WriteStartObject(); 

     foreach (object currObj in collectionObj) 
     { 
      writer.WritePropertyName(m_FieldNameResolver.ResolveFieldName(currObj)); 
      serializer.Serialize(writer, currObj); 
     } 

     writer.WriteEndObject(); 
    } 
} 

,並宣佈以下接口:

public interface IAssociateFieldNameResolver 
{ 
    string ResolveFieldName(object i_Object); 
} 

現在所有剩下要做的,就是創建一個實現IAssociateFieldNameResolver的單一功能,它接受集合中的每個項目類,並返回基於該對象的字符串,這將作爲項目的關聯對象的關鍵。

例對於這樣的一類是:

public class ChannelContextFieldNameResolver : IAssociateFieldNameResolver 
{ 
    public string ResolveFieldName(object i_Object) 
    { 
     return (i_Object as ChannelContext).NominalId; 
    } 
} 
+3

在重寫JsonConverter時,您是如何避免爲ReadJson提供實現的? –

相關問題