I'm working with a project that is using a custom Jackson JsonDeserializer
to deserialize an object with a field containing a third-party object from JSON that cannot be deserialized directly. This deserializer is used by annotating the field with @JsonDeserialize(using = CustomTypeDeserializer.class)
.
public static class OuterType {
@JsonDeserialize(using = CustomTypeDeserializer.class)
private CustomType customType;
public CustomType getCustomType() { return customType; }
public void setCustomType(CustomType customType) { this.customType = customType; }
}
This works fine when the type to be deserialized is a property of another type, since there is a place to put the @JsonDeserialize
annotation. One thing it does not work for is deserializing the type directly.
new ObjectMapper().readValue(json, CustomType.class); // Doesn't work.
It doesn't look like I can use the deserializer directly, as it does not appear to be written in a way that it can directly deserialize values outside of the context of an ObjectMapper
.
Is there a way to deserialize a non-nested type using a custom deserializer?
CodePudding user response:
One approach would be to write a custom Module
containing the deserializer to the module, and add the module to the ObjectMapper
.
public static class CustomTypeModule extends SimpleModule {
public CustomTypeModule() {
addDeserializer(CustomType.class, new CustomTypeDeserializer());
}
}
JsonMapper objectMapper = JsonMapper.builder().addModule(new CustomTypeModule()).build();
CustomType value = objectMapper.readValue(json, CustomType.class);
If you don't want to modify your global application ObjectMapper
(making the module available to all requests), you can apply this to a copy of the ObjectMapper
used just for this operation.
JsonMapper objectMapper = JsonMapper.builder().build();
// ...
JsonMapper customTypeMapper = objectMapper.rebuild().addModule(new CustomTypeModule()).build();
// OR
ObjectMapper customTypeMapper = objectMapper.copy().registerModule(new CustomTypeModule())
CustomType value = customTypeMapper.readValue(json, CustomType.class);
CodePudding user response:
If yours possible scenarios guarantee that a custom deserialer will be always applied over your type not considering if it is nested or not you could apply directly the JsonDeserialize
annotation over your CustomType
class as an alternative to your solution :
@JsonDeserialize(using = CustomTypeDeserializer.class)
public class CustomType {}
If in your json you want to extract the CustomType
object you can use the
readTree
and treeToValue
methods :
//customType object labelled with "customType"
JsonNode tree = mapper.readTree(src).get("customType");
CustomType custom = mapper.treeToValue(tree, CustomType.class);