Джексон с JSON: нераспознанное поле, не помеченное как игнорируемое
Мне нужно преобразовать определенную строку JSON в объект Java. Я использую Джексона для обработки JSON. У меня нет контроля над вводом JSON (я читаю из веб-службы). Это мой входной JSON:
{"wrapper":[{"id":"13","name":"Fred"}]}
Вот упрощенный вариант использования:
private void tryReading() {
String jsonStr = "{\"wrapper\"\:[{\"id\":\"13\",\"name\":\"Fred\"}]}";
ObjectMapper mapper = new ObjectMapper();
Wrapper wrapper = null;
try {
wrapper = mapper.readValue(jsonStr , Wrapper.class);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("wrapper = " + wrapper);
}
Мой класс сущности:
public Class Student {
private String name;
private String id;
//getters & setters for name & id here
}
Мой класс Wrapper - это, по сути, контейнерный объект для получения моего списка учеников:
public Class Wrapper {
private List<Student> students;
//getters & setters here
}
Я продолжаю получать эту ошибку, и "обертка" возвращает null
, Я не уверен, чего не хватает. Может кто-нибудь помочь, пожалуйста?
org.codehaus.jackson.map.exc.UnrecognizedPropertyException:
Unrecognized field "wrapper" (Class Wrapper), not marked as ignorable
at [Source: java.io.StringReader@1198891; line: 1, column: 13]
(through reference chain: Wrapper["wrapper"])
at org.codehaus.jackson.map.exc.UnrecognizedPropertyException
.from(UnrecognizedPropertyException.java:53)
51 ответ
Вы можете использовать аннотацию на уровне класса Джексона:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
@JsonIgnoreProperties
class { ... }
Он будет игнорировать все свойства, которые вы не определили в вашем POJO. Очень полезно, когда вы просто ищете пару свойств в JSON и не хотите писать полное отображение. Больше информации на сайте Джексона. Если вы хотите игнорировать любое не объявленное свойство, вы должны написать:
@JsonIgnoreProperties(ignoreUnknown = true)
Ты можешь использовать
ObjectMapper objectMapper = getObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Он будет игнорировать все свойства, которые не объявлены.
Первый ответ почти правильный, но необходимо изменить метод получения, а НЕ поле - поле является закрытым (и не определяется автоматически); кроме того, геттеры имеют приоритет над полями, если оба видны.(Есть также способы сделать приватные поля видимыми, но если вы хотите получить геттер, нет особого смысла)
Таким образом, получатель должен быть назван getWrapper()
или помечены:
@JsonProperty("wrapper")
Если вы предпочитаете имя метода получения как есть.
Используя Джексон 2.6.0, это сработало для меня:
private static final ObjectMapper objectMapper =
new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
и с настройкой:
@JsonIgnoreProperties(ignoreUnknown = true)
Это может быть достигнуто 2 способами:
Отметьте POJO, чтобы игнорировать неизвестные свойства
@JsonIgnoreProperties(ignoreUnknown = true)
Сконфигурируйте ObjectMapper, который сериализует / десериализует POJO/json, как показано ниже:
ObjectMapper mapper =new ObjectMapper(); // for Jackson version 1.X mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); // for Jackson version 2.X mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
Добавление сеттеров и геттеров решило проблему, и я почувствовал, что проблема заключается в том, как ее решить, а не в том, как подавить / игнорировать ошибку. Я получил ошибку " Нераспознанное поле.. не отмечено как игнорируемое.."
Хотя я использую аннотацию ниже поверх класса, он не смог проанализировать объект json и дать мне ввод
@JsonIgnoreProperties(ignoreUnknown = true)
Затем я понял, что я не добавлял сеттеры и геттеры, после добавления сеттеров и геттеров в "Wrapper" и "Student" это работало как шарм.
Это просто отлично работает для меня
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(
DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
@JsonIgnoreProperties(ignoreUnknown = true)
аннотации не было.
Это работает лучше, чем все, пожалуйста, обратитесь к этой собственности.
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
projectVO = objectMapper.readValue(yourjsonstring, Test.class);
Если вы используете Джексон 2.0
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
Согласно документу вы можете игнорировать выбранные поля или все неизвестные поля:
// to prevent specified fields from being serialized or deserialized
// (i.e. not include in JSON output; or being set even if they were included)
@JsonIgnoreProperties({ "internalId", "secretKey" })
// To ignore any unknown properties in JSON input without exception:
@JsonIgnoreProperties(ignoreUnknown=true)
Это сработало у меня со следующим кодом:
ObjectMapper mapper =new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Я попробовал метод ниже, и он работает для чтения такого формата JSON с Джексоном. Используйте уже предложенное решение: аннотирование геттера с помощью @JsonProperty("wrapper")
Ваш класс обертки
public Class Wrapper{
private List<Student> students;
//getters & setters here
}
Мое предложение класса обертки
public Class Wrapper{
private StudentHelper students;
//getters & setters here
// Annotate getter
@JsonProperty("wrapper")
StudentHelper getStudents() {
return students;
}
}
public class StudentHelper {
@JsonProperty("Student")
public List<Student> students;
//CTOR, getters and setters
//NOTE: If students is private annotate getter with the annotation @JsonProperty("Student")
}
Это, однако, даст вам вывод формата:
{"wrapper":{"student":[{"id":13,"name":Fred}]}}
Также для получения дополнительной информации обратитесь к https://github.com/FasterXML/jackson-annotations
Надеюсь это поможет
Джексон жалуется, потому что не может найти поле в вашем классе Wrapper, которое называется "обертка". Это происходит потому, что у вашего объекта JSON есть свойство, называемое "обертка".
Я думаю, что решение состоит в том, чтобы переименовать поле вашего класса Wrapper в "обертку" вместо "студентов".
На этот вопрос уже есть много ответов. Я добавляю к существующим ответам.
Если вы хотите подать заявку
В вашем файле конфигурации приложения определите bean-компонент для создания такого сопоставителя объектов Jackson.
@Bean
public ObjectMapper getObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return mapper;
}
Теперь вам не нужно отмечать каждый класс, и он проигнорирует все неизвестные свойства.
Спасибо.
Это решение является общим при чтении потоков JSON и требует получения только некоторых полей, в то время как поля, не отображенные в ваших доменных классах, могут быть проигнорированы:
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
Подробным решением будет использование такого инструмента, как jsonschema2pojo, для автоматического создания необходимых классов предметной области, таких как Student, из схемы ответа json. Это можно сделать с помощью любого онлайн-конвертера json в схему.
Простое решение для Java 11 и новее:
var mapper = new ObjectMapper()
.registerModule(new JavaTimeModule())
.disable(FAIL_ON_UNKNOWN_PROPERTIES)
.disable(WRITE_DATES_AS_TIMESTAMPS)
.enable(ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
Важным для игнорирования является отключение «FAIL_ON_UNKNOWN_PROPERTIES».
Как никто не упомянул, думал, что я...
Проблема в том, что ваша собственность в вашем JSON называется "оболочкой", а ваша собственность в Wrapper.class называется "студентами".
Так что либо...
- Исправьте имя свойства в классе или JSON.
- Аннотируйте вашу переменную свойства согласно комментарию StaxMan.
- Аннотируйте сеттер (если он у вас есть)
Аннотируйте полевых студентов, как показано ниже, поскольку в именах свойств json и java есть несоответствие
public Class Wrapper {
@JsonProperty("wrapper")
private List<Student> students;
//getters & setters here
}
Каким-то образом после 45 сообщений и 10 лет никто не опубликовал правильный ответ для моего случая.
@Data //Lombok
public class MyClass {
private int foo;
private int bar;
@JsonIgnore
public int getFoobar() {
return foo + bar;
}
}
В моем случае у нас есть метод под названием
getFoobar()
, но нет
foobar
свойство (потому что оно вычисляется из других свойств).
@JsonIgnoreProperties
по классу не работает.
Решение состоит в том, чтобы аннотировать метод с помощью
@JsonIgnore
Я исправил эту проблему, просто изменив подписи моих методов установки и получения моего класса POJO. Все, что мне нужно было сделать, это изменить метод getObject, чтобы он соответствовал тому, что искал маппер. В моем случае у меня изначально был getImageUrl, но у данных JSON был image_url, который отбрасывал маппер. Я изменил и мои сеттеры, и геттеры на getImage_url и setImage_url.
Надеюсь это поможет.
Это может быть не та же проблема, что и у OP, но в случае, если кто-то попал сюда с той же ошибкой, что и я, это поможет им решить их проблему. Я получил ту же ошибку, что и OP, когда я использовал ObjectMapper из другой зависимости, такой как аннотация JsonProperty.
Это работает:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonProperty;
Не работает:
import org.codehaus.jackson.map.ObjectMapper; //org.codehaus.jackson:jackson-mapper-asl:1.8.8
import com.fasterxml.jackson.annotation.JsonProperty; //com.fasterxml.jackson.core:jackson-databind:2.2.3
То, что работало для меня, должно было сделать собственность публичной. Это решило проблему для меня.
Еще одна возможность - это свойство в application.propertiesspring.jackson.deserialization.fail-on-unknown-properties=false
, который не потребует никакого другого изменения кода в вашем приложении. И когда вы считаете, что договор является стабильным, вы можете удалить это свойство или отметить его как истинное.
Сделайте общедоступными ваши поля класса, а не частными.
public Class Student {
public String name;
public String id;
//getters & setters for name & id here
}
Либо изменить
public Class Wrapper {
private List<Student> students;
//getters & setters here
}
в
public Class Wrapper {
private List<Student> wrapper;
//getters & setters here
}
---- или же ----
Измените строку JSON на
{"students":[{"id":"13","name":"Fred"}]}
Новый Firebase Android внес некоторые огромные изменения; ниже копия документа:
[ https://firebase.google.com/support/guides/firebase-android] :
Обновите ваши объекты модели Java
Как и в 2.x SDK, база данных Firebase автоматически преобразует объекты Java, которые вы передаете DatabaseReference.setValue()
в JSON и может читать JSON в объекты Java, используя DataSnapshot.getValue()
,
В новом SDK при чтении JSON в объект Java с DataSnapshot.getValue()
неизвестные свойства в JSON теперь по умолчанию игнорируются, поэтому вам больше не нужно @JsonIgnoreExtraProperties(ignoreUnknown=true)
,
Чтобы исключить поля / получатели при записи объекта Java в JSON, аннотация теперь называется @Exclude
вместо @JsonIgnore
,
BEFORE
@JsonIgnoreExtraProperties(ignoreUnknown=true)
public class ChatMessage {
public String name;
public String message;
@JsonIgnore
public String ignoreThisField;
}
dataSnapshot.getValue(ChatMessage.class)
AFTER
public class ChatMessage {
public String name;
public String message;
@Exclude
public String ignoreThisField;
}
dataSnapshot.getValue(ChatMessage.class)
Если в вашем JSON есть дополнительное свойство, которого нет в вашем классе Java, вы увидите это предупреждение в файлах журнала:
W/ClassMapper: No setter/field for ignoreThisProperty found on class com.firebase.migrationguide.ChatMessage
Вы можете избавиться от этого предупреждения, поставив @IgnoreExtraProperties
аннотации к вашему классу. Если вы хотите, чтобы база данных Firebase вела себя так же, как в 2.x SDK, и выдает исключение, если есть неизвестные свойства, вы можете поставить @ThrowOnExtraProperties
аннотации к вашему классу.
Ваш вклад
{"wrapper":[{"id":"13","name":"Fred"}]}
указывает, что это объект с полем с именем "обертка", который является коллекцией студентов. Так что моя рекомендация будет,
Wrapper = mapper.readValue(jsonStr , Wrapper.class);
где Wrapper
определяется как
class Wrapper {
List<Student> wrapper;
}
С моей стороны, единственная линия
@JsonIgnoreProperties(ignoreUnknown = true)
тоже не работал
Просто добавь
@JsonInclude(Include.NON_EMPTY)
Джексон 2.4.0
Это отлично сработало для меня
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Если по какой-то причине вы не можете добавить аннотации @JsonIgnoreProperties к своему классу и находитесь внутри веб-сервера / контейнера, такого как Jetty. Вы можете создать и настроить ObjectMapper внутри настраиваемого поставщика.
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
@Provider
public class CustomObjectMapperProvider implements ContextResolver<ObjectMapper> {
private ObjectMapper objectMapper;
@Override
public ObjectMapper getContext(final Class<?> cls) {
return getObjectMapper();
}
private synchronized ObjectMapper getObjectMapper() {
if(objectMapper == null) {
objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
return objectMapper;
}
}