Estou tentando aprender Gson e estou lutando com a exclusão de campo. Aqui estão minhas aulas
public class Student {
private Long id;
private String firstName = "Philip";
private String middleName = "J.";
private String initials = "P.F";
private String lastName = "Fry";
private Country country;
private Country countryOfBirth;
}
public class Country {
private Long id;
private String name;
private Object other;
}
Posso usar o GsonBuilder e adicionar uma ExclusionStrategy para um nome de campo como firstName
ou country
mas não consigo excluir propriedades de determinados campos como country.name
.
Usando o método public boolean shouldSkipField(FieldAttributes fa)
, FieldAttributes não contém informações suficientes para combinar o campo com um filtro semelhante country.name
.
PS: Quero evitar anotações, pois quero melhorar isso e usar o RegEx para filtrar os campos.
Edit : Estou tentando ver se é possível emular o comportamento do plugin JSON do Struts2
usando Gson
<interceptor-ref name="json">
<param name="enableSMD">true</param>
<param name="excludeProperties">
login.password,
studentList.*\.sin
</param>
</interceptor-ref>
Editar: reabri a pergunta com a seguinte adição:
Eu adicionei um segundo campo com o mesmo tipo para esclarecer ainda mais esse problema. Basicamente, quero excluir, country.name
mas não countrOfBirth.name
. Também não quero excluir País como um tipo. Portanto, os tipos são os mesmos, é o local real no gráfico do objeto que eu quero identificar e excluir.
fonte
JsonSerializer
para algum tipo -Country
no seu caso - para o qual é então aplicado eExclusionStrategy
que decide quais campos serializar.Respostas:
Quaisquer campos que você não queira serializar em geral, você deve usar o modificador "transitório", e isso também se aplica aos serializadores json (pelo menos para alguns que eu usei, incluindo o gson).
Se você não quiser que o nome seja exibido no json serializado, forneça uma palavra-chave transitória, por exemplo:
Mais detalhes na documentação do Gson
fonte
transient
vez de@Expose
é que você ainda precisa simular um POJO em seu cliente com todos os campos que possam surgir. No caso de uma API de back-end que pode ser compartilhada entre projetos, isso pode ser problemático. campos adicionais são adicionados. Essencialmente, está na lista de permissões vs lista negra dos campos.Nishant forneceu uma boa solução, mas existe uma maneira mais fácil. Basta marcar os campos desejados com a anotação @Expose, como:
Deixe de fora todos os campos que você não deseja serializar. Em seguida, basta criar seu objeto Gson desta maneira:
fonte
Então, você deseja excluir
firstName
ecountry.name
. Aqui está comoExclusionStrategy
deve ser o seuSe você vê de perto, ele retorna
true
paraStudent.firstName
eCountry.name
, que é o que você deseja excluir.Você precisa aplicar isso
ExclusionStrategy
assim,Isso retorna:
Presumo que o objeto do país seja inicializado
id = 91L
na turma do aluno.Você pode ser extravagante. Por exemplo, você não deseja serializar nenhum campo que contenha a cadeia "name" em seu nome. Faça isso:
Isso retornará:
EDIT: Adicionado mais informações, conforme solicitado.
Isso
ExclusionStrategy
funcionará, mas você precisará passar "Nome do campo totalmente qualificado". Ver abaixo:Aqui está como podemos usá-lo genericamente.
Retorna:
fonte
country.name
usar uma string como e apenas excluir o camponame
ao serializar o campocountry
. Deve ser genérico o suficiente para aplicar a todas as classes que possuem uma propriedade denominada país da classe Country. Eu não quero criar uma ExclusionStrategy para todas as classesDepois de ler todas as respostas disponíveis, descobri que a mais flexível, no meu caso, era usar
@Exclude
anotações personalizadas . Portanto, implementei uma estratégia simples para isso (não queria marcar todos os campos usando@Expose
nem queria usar ostransient
que conflitavam com aSerializable
serialização de aplicativos ):Anotação:
Estratégia:
Uso:
fonte
addSerializationExclusionStrategy
ou emaddDeserializationExclusionStrategy
vez desetExclusionStrategies
f.getAnnotation(Exclude.class) != null
af.getAnnotation(Exclude.class) == null
transient
devido às necessidades de outras bibliotecas. Obrigado!Eu me deparei com esse problema, no qual eu tinha um pequeno número de campos que queria excluir apenas da serialização, então desenvolvi uma solução bastante simples que usa a
@Expose
anotação de Gson com estratégias de exclusão personalizadas.A única maneira interna de usar
@Expose
é definindoGsonBuilder.excludeFieldsWithoutExposeAnnotation()
, mas como o nome indica, os campos sem explícito@Expose
são ignorados. Como eu tinha apenas alguns campos que queria excluir, achei muito provável a possibilidade de adicionar a anotação a todos os campos.Eu queria efetivamente o inverso, no qual tudo estava incluído, a menos que explicitamente o
@Expose
excluísse. Usei as seguintes estratégias de exclusão para fazer isso:Agora, posso excluir facilmente alguns campos com
@Expose(serialize = false)
ou@Expose(deserialize = false)
anotações (observe que o valor padrão para ambos os@Expose
atributos étrue
). É claro que você pode usar@Expose(serialize = false, deserialize = false)
, mas isso é feito de maneira mais concisa ao declarar o campotransient
(o que ainda entra em vigor com essas estratégias de exclusão personalizadas).fonte
Você pode explorar a árvore json com gson.
Tente algo como isto:
Você também pode adicionar algumas propriedades:
Testado com gson 2.2.4.
fonte
Eu vim com uma fábrica de classes para suportar essa funcionalidade. Passe em qualquer combinação de campos ou classes que você deseja excluir.
Para usar, crie duas listas (cada uma é opcional) e crie seu objeto GSON:
fonte
Resolvi esse problema com anotações personalizadas. Esta é minha classe de anotação "SkipSerialisation":
e este é o meu GsonBuilder:
Exemplo:
fonte
@Retention(RetentionPolicy.RUNTIME)
à sua anotação.Ou pode dizer o que os campos não serão expostos com:
na sua classe no atributo:
fonte
excludeFieldsWithModifiers()
isso.Usei esta estratégia: excluí todos os campos que não estão marcados com a anotação @SerializedName , ou seja:
Retorna
fonte
Outra abordagem (especialmente útil se você precisar decidir excluir um campo em tempo de execução) é registrar um TypeAdapter na sua instância gson. Exemplo abaixo:
No caso abaixo, o servidor esperaria um dos dois valores, mas como os dois eram ints, o gson os serializaria. Meu objetivo era omitir qualquer valor que seja zero (ou menos) do json que é postado no servidor.
fonte
A
@Transient
anotação de Kotlin também faz o truque, aparentemente.Resultado:
fonte
Estou trabalhando apenas colocando a
@Expose
anotação, aqui minha versão que eu usoNa
Model
aula:Na
Adapter
classe:fonte
Eu tenho a versão Kotlin
e como você pode adicioná-lo ao Retrofit GSONConverterFactory:
fonte
É isso que eu sempre uso:
O comportamento padrão implementado no Gson é que os campos de objetos nulos são ignorados.
Significa que o objeto Gson não serializa campos com valores nulos para JSON. Se um campo em um objeto Java for nulo, o Gson o excluirá.
Você pode usar esta função para converter algum objeto em nulo ou bem definido por você mesmo.
fonte