serialize objeto deserialize convertir array java json serialization jackson resttemplate

java - deserialize - Deserialización de Jackson Json de un objeto a una lista



json serialize java (2)

Ya que estás usando Jackson, creo que lo que necesitas es la clase JsonDeserializer ( javadoc ).

Puedes implementarlo así:

public class ListOrObjectGenericJsonDeserializer<T> extends JsonDeserializer<List<T>> { private final Class<T> cls; public ListOrObjectGenericJsonDeserializer() { final ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass(); this.cls = (Class<T>) type.getActualTypeArguments()[0]; } @Override public List<T> deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException, JsonProcessingException { final ObjectCodec objectCodec = p.getCodec(); final JsonNode listOrObjectNode = objectCodec.readTree(p); final List<T> result = new ArrayList<T>(); if (listOrObjectNode.isArray()) { for (JsonNode node : listOrObjectNode) { result.add(objectCodec.treeToValue(node, cls)); } } else { result.add(objectCodec.treeToValue(listOrObjectNode, cls)); } return result; } }

...

public class ListOrObjectResultItemJsonDeserializer extends ListOrObjectGenericJsonDeserializer<ResultItem> {}

A continuación, debe anotar su campo POJO. Supongamos que tiene clases como Result y ResultItem :

public class Result { // here you add your custom deserializer so jackson will be able to use it @JsonDeserialize(using = ListOrObjectResultItemJsonDeserializer.class) private List<ResultItem> result; public void setResult(final List<ResultItem> result) { this.result = result; } public List<ResultItem> getResult() { return result; } }

...

public class ResultItem { private String value; public String getValue() { return value; } public void setValue(final String value) { this.value = value; } }

Ahora puedes verificar tu deserializador:

// list of values final String json1 = "{/"result/": [{/"value/": /"test/"}]}"; final Result result1 = new ObjectMapper().readValue(json1, Result.class); // one value final String json2 = "{/"result/": {/"value/": /"test/"}}"; final Result result2 = new ObjectMapper().readValue(json2, Result.class);

result1 y result2 contienen el mismo valor.

Estoy consumiendo un servicio web usando Spring''s RestTemplate y deserializando con Jackson .

En mi respuesta JSON del servidor, uno de los campos puede ser un objeto o una lista. lo que significa que puede ser "result": [{}] o "result": {} .

¿Hay alguna manera de manejar este tipo de cosas mediante anotaciones sobre el tipo al que me estoy deserializando? define el miembro como una array[] o List<> e inserta un único objeto en el caso del segundo ejemplo? ¿Puedo escribir un nuevo HttpMessageConverter que lo maneje?


Puede lograr lo que quiere con un indicador de configuración en ObjectMapper de Jackson:

ObjectMapper mapper = Jackson2ObjectMapperBuilder.json() .featuresToEnable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) .build();

Simplemente configure esta instancia de ObjectMapper en su RestTemplate como se explica en esta respuesta , y en la clase a la que está deserializando, siempre use una colección, es decir, una List :

public class Response { private List<Result> result; // getter and setter }