Reputation: 4559
I am getting data from an external JSON API and parsing the result with Jackson. Unfortunately, that API returns all fields as String
and those are filled with "N/A"
when data is unavailable.
I would like to replace those fields with null
, especially as those are frustrating when I try to convert JSON String fields to more informative Java fields.
A custom DeserializationProblemHandler
worked for Integer
fields (see below), but it was useless for Java 8's LocalDate
fields. Furthermore, it reacts to a problem rather than anticipating it.
I was unable to find a pre-processor to configure into my ObjectMapper
and am uneasy with the idea of overriding the BeanDeserializer
.
Do you know of a better/cleaner solution to handle this kind of situations? Thanks!
DeserializationProblemHandler
new DeserializationProblemHandler() {
@Override
public Object handleWeirdStringValue(DeserializationContext ctxt, Class<?> targetType, String valueToConvert, String failureMsg) throws IOException {
return "N/A".equals(valueToConvert) ? null : super.handleWeirdStringValue(ctxt, targetType, valueToConvert, failureMsg);
}
}
Error message when processing "N/A"
in LocalDate
field
Can not deserialize value of type java.time.LocalDate from String "N/A": Text 'N/A' could not be parsed at index 0
(works fine when there is date in the data)
Upvotes: 7
Views: 2085
Reputation: 7157
I feel like there ought to be a better way of doing this, but the following is the only solution I was able to come up with.
Create a new JsonDeserializer
that handles "N/A" input. The following example handles strings:
public class EmptyStringDeserializer extends StdScalarDeserializer<String> {
public EmptyStringDeserializer() {
super(String.class);
}
@Override
public String deserialize(JsonParser parser, DeserializationContext ctx) throws IOException {
final String val = parser.getValueAsString();
if ("N/A".equalsIgnoreCase(val))
return null;
return val;
}
}
The class is registered with an ObjectMapper
like this:
SimpleModule simpleModule = new SimpleModule().addDeserializer(String.class, new EmptyStringDeserializer());
ObjectMapper om = new ObjectMapper().registerModule(simpleModule);
You'll probably want to collect all your converters in a module named for the API that is making you handle things this way.
Upvotes: 1