Temos alguns arquivos de configuração que foram gerados serializando objetos C # com Json.net.
Gostaríamos de migrar uma propriedade da classe serializada de uma propriedade de enum simples para uma propriedade de classe.
Uma maneira fácil de fazer isso seria deixar a propriedade enum antiga na classe e fazer com que o Json.net leia essa propriedade quando carregarmos a configuração, mas não salvá-la novamente na próxima serialização do objeto. Lidaremos com a geração da nova classe do enum antigo separadamente.
Existe alguma maneira simples de marcar (por exemplo, com atributos) uma propriedade de um objeto C #, de modo que Json.net irá ignorá-lo SOMENTE ao serializar, mas prestar atenção a ele ao desserializar?
Respostas:
Na verdade, existem várias abordagens bastante simples que você pode usar para alcançar o resultado desejado.
Vamos supor, por exemplo, que você tem suas classes atualmente definidas assim:
E você quer fazer isso:
Para conseguir esta:
Abordagem 1: Adicionar um método ShouldSerialize
Json.NET tem a capacidade de serializar propriedades condicionalmente, procurando por
ShouldSerialize
métodos correspondentes na classe.Para usar este recurso, adicione um
ShouldSerializeBlah()
método booleano à sua classe, ondeBlah
é substituído pelo nome da propriedade que você não deseja serializar. Faça a implementação deste método sempre retornarfalse
.Observação: se você gosta dessa abordagem, mas não quer complicar a interface pública de sua classe com a introdução de um
ShouldSerialize
método, pode usar umIContractResolver
para fazer a mesma coisa programaticamente. Consulte Serialização condicional de propriedade na documentação.Abordagem 2: Manipular o JSON com JObjects
Em vez de usar
JsonConvert.SerializeObject
para fazer a serialização, carregue o objeto de configuração em umJObject
e simplesmente remova a propriedade indesejada do JSON antes de escrevê-lo. São apenas algumas linhas extras de código.Abordagem 3: uso inteligente (ab) de atributos
[JsonIgnore]
atributo à propriedade que você não deseja que seja serializada.[JsonProperty]
atributo ao configurador alternativo, dando a ele o mesmo nome JSON da propriedade original.Aqui está a
Config
aula revisada :fonte
JsonPropertyAttribute
, a partir do C # 6.0, você pode usar anameof
palavra - chave em vez de usar "strings mágicas". Isso torna a refatoração muito mais fácil e à prova de idiotas - além disso, se você deixar de renomear qualquer ocorrência, o compilador irá avisá-lo de qualquer maneira. Usando o exemplo de @Brian, o uso seria este:[JsonProperty(nameof(ObsoleteSetting))]
Para qualquer situação em que seja aceitável ter sua propriedade somente de desserialização marcada como interna, há uma solução incrivelmente simples que não depende de atributos. Basta marcar a propriedade como get interno, mas definir público:
Isso resulta na desserialização correta usando configurações / resolvedores padrão / etc., Mas a propriedade é removida da saída serializada.
fonte
get
método público ).internal
nemprivate
. É sempre serializado.Eu gosto de manter os atributos neste aqui, aqui está o método que uso quando preciso desserializar uma propriedade, mas não serializá-la ou vice-versa.
PASSO 1 - Crie o atributo personalizado
ETAPA 2 - Crie um Reslover de contrato personalizado
ETAPA 3 - Adicionar atributo onde a serialização não é necessária, mas a desserialização é
PASSO 4 - Use-o
Espero que isto ajude! Também é importante notar que isso também irá ignorar as propriedades quando ocorrer a desserialização, quando estou deserializando, utilizo apenas o conversor da forma convencional.
fonte
GetSerializableMembers
vez de substituí-la inteiramente?return base.GetSerializableMembers(objectType).Where(pi => !Attribute.IsDefined(pi, typeof(JsonIgnoreSerializationAttribute))).ToList();
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { ContractResolver = new JsonPropertiesResolver() }
Use a propriedade setter:
Espero que esta ajuda.
fonte
IgnoreOnSerializing
, igual à propriedade. Eu recomendo usarnameof(IgnoreOnSerializing)
para evitar string mágica, em caso de renomeação.Depois de passar um longo tempo procurando como sinalizar uma propriedade de classe como De-Serializable e NÃO Serializable, descobri que não existe tal coisa para fazer isso; então eu vim com uma solução que combina duas bibliotecas ou técnicas de serialização diferentes (System.Runtime.Serialization.Json & Newtonsoft.Json) e funcionou para mim da seguinte forma:
em seguida, serialize usando "Newtonsoft.Json.JsonConvert.SerializeObject" e De-Serialize usando "System.Runtime.Serialization.Json.DataContractJsonSerializer".
Espero que ajude ...
fonte
com referência à solução de @ThoHo, usar o setter é na verdade tudo o que é necessário, sem tags adicionais.
Para mim, anteriormente, eu tinha um único ID de referência, que queria carregar e adicionar à nova coleção de IDs de referência. Alterando a definição do Id de referência para conter apenas um método setter, que agregou o valor à nova coleção. Json não pode escrever o valor de volta se a propriedade não tiver um get; método.
Esta classe agora é compatível com a versão anterior e salva apenas os RefIds para as novas versões.
fonte
Para desenvolver a resposta de Tho Ho, isso também pode ser usado para campos.
fonte
Dependendo de onde isso ocorre no aplicativo e se for apenas uma propriedade, uma maneira manual de fazer isso é definindo o valor da propriedade como nulo e, em seguida, no modelo, você pode especificar que a propriedade seja ignorada se o valor for nulo:
Se você estiver trabalhando em um aplicativo da web ASP.NET Core, poderá definir isso globalmente para todas as propriedades em todos os modelos, definindo isso em seu arquivo Startup.cs:
fonte
Se você usar JsonConvert, IgnoreDataMemberAttribute está ok.Minha biblioteca padrão não refrence Newton.Json, e eu uso [IgnoreDataMember] para controlar a serialização de objetos.
Do documento de ajuda Newton.net .
fonte
A maneira mais fácil que encontrei até o momento desta escrita é incluir essa lógica em seu IContractResolver .
Exemplo de código do link acima copiado aqui para a posteridade:
Todas as respostas são boas, mas essa abordagem parecia a maneira mais limpa. Na verdade, eu implementei isso procurando um atributo na propriedade para SkipSerialize e SkipDeserialize para que você possa apenas marcar qualquer classe que você controlar. Ótima pergunta!
fonte