serialize example java json spring jackson

example - objectmapper java



Cómo aplicar ACCEPT_SINGLE_VALUE_AS_ARRAY en el proceso de deserialización de jackson mediante anotación (3)

¿Hay alguna forma de usar la anotación en una propiedad de la lista en una clase para usar ACCEPT_SINGLE_VALUE_AS_ARRAY en Jackson? Estoy usando Spring y obtengo la siguiente excepción

la excepción anidada es com.fasterxml.jackson.databind.JsonMappingException: no se puede deserializar la instancia de java.util.ArrayList fuera de la ficha VALUE_STRING

Supongamos que tengo una clase como la siguiente:

public class MyClass { . . private List<String> value; . . }

Y mis estructuras JSON son las siguientes:

caso 1:

[{"operator": "in", "value": ["Active"], "property": "status"}]

caso 2:

[{"operator": "like", "value": "aba", "property": "desc"}]

¿Qué anotación debería usar para dejar que el marco de trabajo sepa que quiero que estos 2 casos sean tratados de la misma manera cuando se deserializan?

ACTUALIZACIÓN: Moví las actualizaciones a una respuesta en esta publicación para mayor claridad.


Con la anotación @JsonFormat :

public class MyClass { . . @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) private List<String> value; . . }

puedes consultar la versión de otras opciones desde aquí

y requerido (mínimo 2.7.0)

para 2.6.x

@Autowired private ObjectMapper mapper; //..... mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

agregue este código a su clase de inicializador.

o puede configurar directamente jackson en la configuración de bean de su primavera.

esta configuración resolvería el problema, pero esto se activará para cada deserialización.


Solo estoy respondiendo mi propia pregunta para mayor claridad. Una de las respuestas fue actualizar a la versión superior para que pueda usar las anotaciones. No puedo hacerlo debido a las restricciones de dependencia de mi proyecto.

Como resultado, basado en la respuesta de Michal Foksa, resolví mi problema creando un deserializador personalizado. Es como a continuación:

En mi propiedad:

@JsonDeserialize(using = CustomStringDeserializer.class) private List<String> value;

Y mi Deserializador:

public class CustomStringDeserializer extends JsonDeserializer<List<String>>{ @Override public List<String> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature. ACCEPT_SINGLE_VALUE_AS_ARRAY); return mapper.readValue(p, List.class); } }


JsonDeserializer un JsonDeserializer personalizado donde trataría ambos casos y JsonDeserializer propiedad de clase de valor con el deserializador.

Deserializador:

public class StringListDeserializer extends JsonDeserializer<List<String>>{ @Override public List<String> deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JsonProcessingException { List<String> ret = new ArrayList<>(); ObjectCodec codec = parser.getCodec(); TreeNode node = codec.readTree(parser); if (node.isArray()){ for (JsonNode n : (ArrayNode)node){ ret.add(n.asText()); } } else if (node.isValueNode()){ ret.add( ((JsonNode)node).asText() ); } return ret; } }

Mi clase:

public class MyClass { . @JsonDeserialize(using = StringListDeserializer.class) private List<String> value; . }

Espero eso ayude.

Por cierto: si hay una manera de lidiar con un caso así con solo una anotación, también quiero saberlo.