Desserializar string como lista de strings
Eu tenho um POJO que contém os seguintes atributos
public class Example {
@JsonProperty("inputFoo")
private String foo
@JsonProperty("inputBar")
private String bar
@JsonProperty("inputBaz")
@JsonDeserialize(using = MyDeserializer.class)
private Set<String> baz
}
O JSON com o qual estou trabalhando para representar esses dados atualmente representa o atributo baz como uma única string:
{"inputFoo":"a", "inputBar":"b", "inputBaz":"c"}
Estou usando o Jackson ObjectMapper para tentar converter o JSON em meu POJO. Eu sei que a string de baz de entrada do JSON não será mapeada corretamente para o conjunto que estou tentando representá-la, então defini um desserializador personalizado:
public class MyDeserializer extends StdDeserializer<Set<String>> {
public MyDeserializer(){}
public MyDeserializer(Class<?> vc) {
super(vc);
}
public Set<String> deserialize(JsonParser p, DeserializationContext cxt) throws IOException, JsonProcessingException {
String input = p.readValueAs(String.class);
Set<String> output = new HashSet<>();
if(input != null) {
output.add(input);
}
return output;
}
}
Estou recebendo uma IllegalArgumentException que faz referência ao atributo "inputBaz", sobre a qual posso fornecer detalhes. Alguém vê algum problema óbvio com a implementação do meu desserializador? obrigado
Respostas
Você não precisa implementar o desserializador personalizado, use o recurso ACCEPT_SINGLE_VALUE_AS_ARRAY . Também funciona para conjuntos:
Recurso que determina se é aceitável coagir valores não-array (em JSON) para trabalhar com tipos de coleção Java (arrays, java.util.Collection) . Se habilitado, os desserializadores de coleção tentarão manipular valores que não sejam de matriz como se eles tivessem "implícito" a matriz JSON. Esse recurso deve ser usado por motivos de compatibilidade / interoperabilidade, para trabalhar com pacotes (como conversores XML-para-JSON) que omitem o array JSON nos casos em que há apenas um único elemento no array. O recurso está desabilitado por padrão.
Veja também:
- com.fasterxml.jackson.databind.exc.MismatchedInputException: Não é possível desserializar a instância do java.util.ArrayListtoken START_OBJECT
Substitua os 2 construtores por este construtor sem argumentos:
public MyDeserializer() {
super(TypeFactory.defaultInstance().constructCollectionType(Set.class, String.class));
}
ACCEPT_SINGLE_VALUE_AS_ARRAY como sugerido é uma boa opção.
Talvez o seu problema real seja mais complicado, mas se não, você também pode tentar em @JsonCreatorvez do desserializador personalizado. Gostar:
public class Example {
@JsonCreator
public Example(@JsonProperty("inputFoo") String foo,
@JsonProperty("inputBar") String bar,
@JsonProperty("inputBaz") String strBaz) {
this.foo = foo;
this.bar = bar;
this.baz = new HashSet<>();
baz.add(strBaz);
}
private String foo;
private String bar;
private Set<String> baz;
}
Apenas para mostrar que, em casos mais gerais, você pode evitar a implementação do desserializador personalizado com @JsonCreatortambém, mas ainda assim fazer algumas conversões simples.