Serialização de Json personalizada de class

Eu tenho código estruturado como abaixo.

public class Stats { public string URL { get; set; } public string Status { get; set; } public string Title { get; set; } public string Description { get; set; } public int Length { get; set; } } 

e

  public class UrlStats { public string URL { get; set; } public int TotalPagesFound { get; set; } public List TotalPages { get; set; } public int TotalTitleTags { get; set; } public List TotalTitles { get; set; } public int NoDuplicateTitleTags { get; set; } public List DuplicateTitles { get; set; } public int NoOverlengthTitleTags { get; set; } public List OverlengthTitles { get; set; } } 

Basicamente eu estou digitalizando um site para statistics como tags de título, títulos duplicados, etc.

Estou usando o JQuery e fazendo chamadas AJAX para o serviço da Web e recuperando as statistics do URL enquanto o processo está sendo executado para mostrar as statistics do URL do usuário, de longe coletadas, pois leva um bom tempo para verificar um site grande. Então, a cada 5 segundos eu recupero as statistics do servidor. Agora, o problema são todos os dados variables ​​da lista que eu preciso enviar no final quando o processamento da verificação estiver concluído, não durante as atualizações. O que está acontecendo agora mesmo, os dados variables ​​da List também são enviados durante as atualizações, o que é grande parte dos dados e eu quero enviar apenas as variables ​​do tipo int que são necessárias para mostrar as atualizações do processo.

De pesquisar na internet eu não consegui encontrar nada de útil para resolver o meu problema e descobri que Json.NET é uma biblioteca muito boa, mas eu realmente não sei como usá-lo corretamente para conseguir o que eu quero.

Basicamente eu estou procurando propriedades de serialização dependendo do seu tipo de dados em tempo de execução, se for possível.

Existem duas abordagens diferentes para o seu problema.

Você deve escolher o primeiro caso queira alterar suas classs com mais frequência porque a primeira abordagem impede que você esqueça de serializar uma propriedade recém-adicionada. Além disso, é muito mais reutilizável se você quiser adicionar outras classs que você deseja que sejam serializadas da mesma maneira.

Se você tem apenas essas duas classs e é mais provável que elas não mudem, você pode escolher a segunda abordagem para manter sua solução simples.

1. Use um conversor personalizado para selecionar todas as propriedades int

A primeira abordagem é usar um JsonConverter personalizado que serialize uma class ou struct incluindo apenas propriedades que possuem tipo int . O código pode ser assim:

 class IntPropertyConverter : JsonConverter { public override bool CanConvert(Type objectType) { // this converter can be applied to any type return true; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // we currently support only writing of JSON throw new NotImplementedException(); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) { serializer.Serialize(writer, null); return; } // find all properties with type 'int' var properties = value.GetType().GetProperties().Where(p => p.PropertyType == typeof(int)); writer.WriteStartObject(); foreach (var property in properties) { // write property name writer.WritePropertyName(property.Name); // let the serializer serialize the value itself // (so this converter will work with any other type, not just int) serializer.Serialize(writer, property.GetValue(value, null)); } writer.WriteEndObject(); } } 

Então você tem que decorar sua class com um JsonConverterAttribute :

 [JsonConverter(typeof(IntPropertyConverter))] public class UrlStats { // ... } 

Disclaimer: Este código foi testado apenas aproximadamente.


2. Escolha propriedades individualmente

A segunda solução parece um pouco mais simples: você pode usar o JsonIgnoreAttribute para decorar os atributos que deseja excluir para a serialização. Como alternativa, você pode alternar de “lista negra” para “lista de permissions”, incluindo explicitamente os atributos que deseja serializar. Aqui está um pouco de código de amostra:

Lista negra: (reordenei as propriedades para uma melhor visão geral)

 [JsonObject(MemberSerialization.OptOut)] // this is default and can be omitted public class UrlStats { [JsonIgnore] public string URL { get; set; } [JsonIgnore] public List TotalPages { get; set; } [JsonIgnore] public List TotalTitles { get; set; } [JsonIgnore] public List DuplicateTitles { get; set; } [JsonIgnore] public List OverlengthTitles { get; set; } public int TotalPagesFound { get; set; } public int TotalTitleTags { get; set; } public int NoDuplicateTitleTags { get; set; } public int NoOverlengthTitleTags { get; set; } } 

Whitelisting: (também reordenado)

 [JsonObject(MemberSerialization.OptIn)] // this is important! public class UrlStats { public string URL { get; set; } public List TotalPages { get; set; } public List TotalTitles { get; set; } public List DuplicateTitles { get; set; } public List OverlengthTitles { get; set; } [JsonProperty] public int TotalPagesFound { get; set; } [JsonProperty] public int TotalTitleTags { get; set; } [JsonProperty] public int NoDuplicateTitleTags { get; set; } [JsonProperty] public int NoOverlengthTitleTags { get; set; } } 

Ah, entendi, relendo sua pergunta Acho que você pode serializar uma projeção de seus dados.

Você pode tentar o seguinte:

 var json = JsonConvert.SerializeObject(new { u.TotalPagesFound, u.TotalTitleTags, u.NoDuplicateTitleTags, u.NoOverlengthTitleTags } ); 

Isso converterá em JSON apenas as propriedades int da sua class. Essa é a maneira mais fácil e está ligada à estrutura da sua class. Se você quiser algo mais geral, você precisará implementar um conversor personalizado.

Resposta original:

Eu não vejo nenhum problema com suas classs, você não tem nada estranho como referências de loop, então o Json.NET não deve ter nenhum problema em serializar sua class. Então, vá pegar Json.NET e então você pode tentar o seguinte

 // create new instance of your url stat class var u = new UrlStats() { URL = "a.com", TotalPages = new List() { new Stats() { URL = "b.com", Status = "xxxx" } } }; // seralize! var json = JsonConvert.SerializeObject(u); Console.Write(json); 

O que eu recebo com esse método é algo assim:

 {"URL":"a.com","TotalPagesFound":0,"TotalPages":[{"URL":"b.com","Status":"xxxx","Title":null,"Description":null,"Length":0}],"TotalTitleTags":0,"TotalTitles":null,"NoDuplicateTitleTags":0,"DuplicateTitles":null,"NoOverlengthTitleTags":0,"OverlengthTitles":null} 

E isso parece bom json para mim.