Como obtenho o json.net para serializar membros de uma class derivada de List ?

Eu criei uma class PagedResult : List que contém alguns membros adicionados para trabalhar com um dos nossos componentes. No entanto, quando eu executo o desserializador json, ele apenas serializa a lista. Se eu marcar a class derivada com [JsonObject] e [JsonProperty] , ela só serializará os membros da class derivada e não a lista. Como obtenho os dois?

Por padrão, o Json.Net tratará qualquer class que implemente IEnumerable como uma matriz. Você pode replace esse comportamento decorando a class com um atributo [JsonObject] , mas somente as propriedades do object serão serializadas, como você viu. A lista em si não será serializada porque não é exposta por meio de uma propriedade pública (em vez disso, é exposta por meio do método GetEnumerator() ).

Se você quer tanto, você pode fazer como @Konrad sugeriu e fornecer uma propriedade pública em sua class derivada para expor a lista, ou você pode escrever um JsonConverter personalizado para serializar a coisa toda como achar melhor. Um exemplo da última abordagem segue.

Supondo que sua PagedResult algo como isto:

 class PagedResult : List { public int PageSize { get; set; } public int PageIndex { get; set; } public int TotalItems { get; set; } public int TotalPages { get; set; } } 

Você pode fazer um conversor para isso assim:

 class PagedResultConverter : JsonConverter { public override bool CanConvert(Type objectType) { return (objectType == typeof(PagedResult)); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { PagedResult result = (PagedResult)value; JObject jo = new JObject(); jo.Add("PageSize", result.PageSize); jo.Add("PageIndex", result.PageIndex); jo.Add("TotalItems", result.TotalItems); jo.Add("TotalPages", result.TotalPages); jo.Add("Items", JArray.FromObject(result.ToArray(), serializer)); jo.WriteTo(writer); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } } 

(Observe também que os [JsonObject] e [JsonProperty] não são necessários com essa abordagem, porque o conhecimento do que serializar é encapsulado na class do conversor.)

Aqui está uma demonstração mostrando o conversor em ação:

 class Program { static void Main(string[] args) { PagedResult result = new PagedResult { "foo", "bar", "baz" }; result.PageIndex = 0; result.PageSize = 10; result.TotalItems = 3; result.TotalPages = 1; JsonSerializerSettings settings = new JsonSerializerSettings(); settings.Converters.Add(new PagedResultConverter()); settings.Formatting = Formatting.Indented; string json = JsonConvert.SerializeObject(result, settings); Console.WriteLine(json); } } 

Saída:

 { "PageSize": 10, "PageIndex": 0, "TotalItems": 3, "TotalPages": 1, "Items": [ "foo", "bar", "baz" ] } 

A solução mais simples que me vem à mente é expor elementos internos como outra propriedade da class derivada:

 [JsonProperty] public IEnumerable Elements { get { return this; } }