Для вашей проблемы не существует решения только для аннотаций. Каким-то образом вам нужно конвертировать JSON Object
в java.lang.String
и вам нужно указать это преобразование.
Вы можете:
- Написать собственный десериализатор, который, вероятно, является наиболее очевидным решением, но запрещен в вопрос.
- Зарегистрируйте пользовательский
com.fasterxml.jackson.databind.deser.DeserializationProblemHandler
и обработайте ситуацию com.fasterxml.jackson.databind.exc.MismatchedInputException
более сложным способом. - Реализуйте интерфейс
com.fasterxml.jackson.databind.util.Converter
и преобразуйте JsonNode
в String
. Это полуаннотационный способ решения проблемы, но мы не реализуем худшую часть - десериализацию.
Давайте сразу же go до пункта 2.
2. DeserializationProblemHandler
Решение довольно простое:
ObjectMapper mapper = new ObjectMapper();
mapper.addHandler(new DeserializationProblemHandler() {
@Override
public Object handleUnexpectedToken(DeserializationContext ctxt, JavaType targetType, JsonToken t, JsonParser p, String failureMsg) throws IOException {
if (targetType.getRawClass() == String.class) {
// read as tree and convert to String
return p.readValueAsTree().toString();
}
return super.handleUnexpectedToken(ctxt, targetType, t, p, failureMsg);
}
});
Считать целый фрагмент JSON
как TreeNode
и преобразовать его в String
, используя метод toString
. Полезно, toString
генерирует действительные JSON
. Недостатком этого решения является глобальная область действия для данного ObjectMapper
экземпляра.
3. Пользовательский конвертер
Это решение требует реализации интерфейса com.fasterxml.jackson.databind.util.Converter
, который преобразует com.fasterxml.jackson.databind.JsonNode
в String
:
class JsonNode2StringConverter implements Converter<JsonNode, String> {
@Override
public String convert(JsonNode value) {
return value.toString();
}
@Override
public JavaType getInputType(TypeFactory typeFactory) {
return typeFactory.constructType(new TypeReference<JsonNode>() {
});
}
@Override
public JavaType getOutputType(TypeFactory typeFactory) {
return typeFactory.constructType(new TypeReference<String>() {
});
}
}
, и теперь вы можете использовать аннотацию, как показано ниже:
@JsonDeserialize(contentConverter = JsonNode2StringConverter.class)
private List<String> companies;
Решения 2. и 3. Решить эту проблему почти одинаково - прочитать узел и преобразовать его обратно в JSON
, но использовать разные подходы.
Если вы хотите избежать десериализации и В процессе сериализации вы можете взглянуть на решение, предоставленное в этой статье: Десериализация JSON свойства как строки с Джексоном и взглянуть на: