Jackson desrialize when JsonProperty is sometimes an array, and sometimes a single object

I searched for qaru before publishing, but there were no solutions for Jackson.

Here is the server response:

{ "ok": true, "result": [ { "update_id": 489881731, //rest }, { "update_id": 489881732, //rest } ] } 

As you can see, the "result" property is an array.

Now this is another answer:

 { "ok": true, "result": { "id": 211948704, "first_name": "ربات ادمین‌های تلگرام", "username": "tgAdminsBot" } } 

Here "result" is one object.

This is my class, I want to deserialize the content. I wrote a custom deserializer for TObject , of course:

 public class Result { private TObject[] result; private boolean ok; public void setOk (boolean ok) {//code} public void setResult (TObject[] result) {//code} public TObject[] getResult () {//code} public boolean getOk (){//code} } 

Therefore, I suggested in my class that " result" is an array of TObject s. Now what can I do? Uses @JsonProperty("result") for two fields, one of which is a TObject array and one is a single TObject OK?

If not, what else can I do?

+8
source share
2 answers

If you enable DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY as

{"result": []} and

{"result": {}} can be analyzed as

 class Result{ List result; } 

Documentation Link

A function that determines whether forced use of a non-array (in JSON) is acceptable for working with a Java collection (arrays, java.util.Collection). If enabled, collector deserializers will try to handle values ​​other than an array, as if they had an "implicit" JSON environment. This function is intended to be used for compatibility / compatibility, for working with packages (for example, XML-to-JSON converters) that do not take into account the JSON array in cases where it is just one element in the array. By default, the function is disabled.

Demo how to use it for OP and POJO I / O:

 ObjectMapper mapper = new ObjectMapper() mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); Result result = mapper.readValue(Result.class; 

Can be used with @JsonFormat over a class or field if for some reason you don't like the mapper version

 @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) 

PS. Other questions on this issue: LINK

+7
source

The best way to solve this problem is when using RestTemplate.

 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; ObjectMapper objectMapper = new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, false); MappingJackson2HttpMessageConverter jacksonMappingConverter = new MappingJackson2HttpMessageConverter(objectMapper); restTemplate.getMessageConverters().add(0, jacksonMappingConverter); 

For the element to be analyzed, use annotation, which can be an object or an array, as follows

 import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; public class ParentObject{ @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) @JsonProperty("InnerObject") private List<InnerObject> innerObject; 

}

If you do not want to add a new mapper in restTemplate, modify the existing one to support the use case

 List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters(); for (HttpMessageConverter<?> httpMessageConverter : messageConverters) { if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter) { MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) httpMessageConverter; mappingJackson2HttpMessageConverter.getObjectMapper() .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); } } 
0
source

All Articles