2011-06-19 35 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提供实现的? –

相关问题