Джексон с 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: [email protected]; line: 1, column: 13] 
    (through reference chain: Wrapper["wrapper"])
 at org.codehaus.jackson.map.exc.UnrecognizedPropertyException
    .from(UnrecognizedPropertyException.java:53)

44 ответа

Вы можете использовать аннотацию на уровне класса Джексона:

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 способами:

  1. Отметьте POJO, чтобы игнорировать неизвестные свойства

    @JsonIgnoreProperties(ignoreUnknown = true)
    
  2. Сконфигурируйте 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) 
    

Это просто отлично работает для меня

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);

Добавление сеттеров и геттеров решило проблему, и я почувствовал, что проблема заключается в том, как ее решить, а не в том, как подавить / игнорировать ошибку. Я получил ошибку " Нераспознанное поле.. не отмечено как игнорируемое.."

Хотя я использую аннотацию ниже поверх класса, он не смог проанализировать объект json и дать мне ввод

@JsonIgnoreProperties(ignoreUnknown = true)

Затем я понял, что я не добавлял сеттеры и геттеры, после добавления сеттеров и геттеров в "Wrapper" и "Student" это работало как шарм.

Если вы используете Джексон 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 в "обертку" вместо "студентов".

Это решение является общим при чтении потоков JSON и требует получения только некоторых полей, в то время как поля, не отображенные в ваших доменных классах, могут быть проигнорированы:

import org.codehaus.jackson.annotate.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)

Подробным решением будет использование такого инструмента, как jsonschema2pojo, для автоматического создания необходимых классов предметной области, таких как Student, из схемы ответа json. Это можно сделать с помощью любого онлайн-конвертера json в схему.

Аннотируйте полевых студентов, как показано ниже, поскольку в именах свойств json и java есть несоответствие

public Class Wrapper {
    @JsonProperty("wrapper")
    private List<Student> students;
    //getters & setters here
}

Как никто не упомянул, думал, что я...

Проблема в том, что ваша собственность в вашем JSON называется "оболочкой", а ваша собственность в Wrapper.class называется "студентами".

Так что либо...

  1. Исправьте имя свойства в классе или JSON.
  2. Аннотируйте вашу переменную свойства согласно комментарию StaxMan.
  3. Аннотируйте сеттер (если он у вас есть)

Сделайте общедоступными ваши поля класса, а не частными.

public Class Student { 
    public String name;
    public String id;
    //getters & setters for name & id here
}

То, что работало для меня, должно было сделать собственность публичной. Это решило проблему для меня.

Если по какой-то причине вы не можете добавить аннотации @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;
    }
}

Ваш вклад

{"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

Либо изменить

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 аннотации к вашему классу.

Еще одна возможность - это свойство в application.propertiesspring.jackson.deserialization.fail-on-unknown-properties=false, который не потребует никакого другого изменения кода в вашем приложении. И когда вы считаете, что договор является стабильным, вы можете удалить это свойство или отметить его как истинное.

Это отлично сработало для меня

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Я исправил эту проблему, просто изменив подписи моих методов установки и получения моего класса 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

Это может быть очень поздний ответ, но простое изменение POJO на это должно решить строку json, представленную в задаче (поскольку входная строка не находится под вашим контролем, как вы сказали):

public class Wrapper {
    private List<Student> wrapper;
    //getters & setters here
}

POJO должен быть определен как

Класс ответа

public class Response {
    private List<Wrapper> wrappers;
    // getter and setter
}

Класс Wrapper

public class Wrapper {
    private String id;
    private String name;
    // getters and setters
}

и картограф для чтения значения

Response response = mapper.readValue(jsonStr , Response.class);

Параметр FAIL_ON_UNKNOWN_PROPERTIES по умолчанию истинен:

FAIL_ON_UNKNOWN_PROPERTIES (default: true)
Used to control whether encountering of unknown properties (one for which there is no setter; and there is no fallback "any setter" method defined using @JsonAnySetter annotation) should result in a JsonMappingException (when enabled), or just quietly ignored (when disabled)
Другие вопросы по тегам