如果有人对我的解决方案感兴趣:
在序列化某些集合时,我想创建一个关联的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; }}响应上下文包含整个响应,该响应被写回到客户端,如您所见,它包含一个称为“通道”的部分,并且我不想在常规数组中输出channelcontext,而是希望在以下方式:
"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; }}


