Джексон бросает JsonMappingException при десериализации; требует однострочный конструктор?
Другой вопрос, но он относится к этому:
Дезабилизация JSON с помощью Jackson - Почему JsonMappingException "Нет подходящего конструктора" ?
На этот раз я получаю другую ошибку, а именно, что десериализатор Джексона жалуется, что у меня нет метода "single-String constructor/ factory" в моем классе ProtocolContainer.
Однако, если я добавлю однострочный конструктор, например:
public ProtocolContainer(String json) {}
исключение действительно исчезает, но ProtocolContainer
, который я ожидал там, есть все "пустые", т.е. все его свойства находятся в их исходном состоянии и не заполняются в соответствии со строкой JSON.
Почему это?
Я уверен, что вам не нужен конструктор с одним строком, и если вы это сделаете, вам не нужно будет заполнять свойства в этом конструкторе, верно?
=)
Ответы
Ответ 1
О, так что еще раз я узнал ответ ПОСЛЕ того, как я разместил этот вопрос (хотя я и пробовал много вещей перед публикацией).
Что я сделал для решения этой проблемы, так это использовать аннотацию @JsonCreator
. Я просто аннотировал мой статический метод Create
, например:
@JsonCreator
public static ProtocolContainer Create(String jsonString)
{
ProtocolContainer pc = null;
try {
pc = mapper.readValue(jsonString, ProtocolContainer.class);
} catch (JsonParseException|JsonMappingException|IOException e) {
// handle
}
return pc;
}
И тогда проблема решена.
Ответ 2
Исключение указывает на то, что значение JSON у вас есть String, что-то вроде:
{ "protocol" : "http" }
или, возможно, "JSON с двойными кавычками":
"\"{\"property\":\"value\"}\"
при попытке привязки как:
ProtocolContainer p = mapper.readValue(json, ProtocolContainer.class);
и в этом случае у Jackson нет свойств для отображения, просто String. И в этом случае он действительно требует либо настраиваемого десериализатора, либо метода создателя. Творческие методы - это либо конструкторы с одним строковым аргументом, либо однострочные аргументы статические методы: разница состоит в том, что только конструкторы могут быть автоматически обнаружены (это просто практическое сокращение, поскольку может быть только один такой конструктор, но несколько статические методы).
Ваше решение действительно работает, просто подумал, что я расскажу немного о том, что происходит.
Прочитав это во второй раз, кажется, что у вас есть вещи с двойным цитированием (JSON в JSON): еще одна вещь, которую следует учитывать, - это получить простой JSON, если это возможно. Но, возможно, это трудно сделать.
Ответ 3
У меня была та же проблема. Для меня решение заключалось в том, чтобы перейти от передачи метода String
к convertValue
в метод InputStream
к readValue
:
// Instead of this:
String jsonString = "..."
ProtocolContainer pc = mapper.convertValue(jsonString, ProtocolContainer.class);
// ... do this:
String jsonString = "..."
InputStream is = new StringInputStream(jsonString);
ProtocolContainer pc = mapper.readValue(is, ProtocolContainer.class);
Ответ 4
Кажется, что вы отправляете на сервер строку вместо объекта.
Вместо отправки строки, подлежащей анализу на стороне сервера, вы можете сделать это проще, просто отправив JSON.parse(stringObject)
, и Джексон будет десериализовать ее как обычно.