Как я могу сказать Джексону игнорировать свойство, для которого у меня нет контроля над исходным кодом?

Короче говоря, одна из моих сущностей имеет коллекцию GeometryCollection, которая выдает исключение, когда вы вызываете "getBoundary" (почему это еще одна книга, а сейчас давайте скажем, что так оно и работает).

Есть ли способ, которым я могу сказать Джексону не включать этот конкретный получатель? Я знаю, что могу использовать @JacksonIgnore, когда владею / управляю кодом. Но это не так, Джексон завершает достижение этой точки путем непрерывной сериализации родительских объектов. Я видел вариант фильтрации в документации Джексона. Это правдоподобное решение?

Спасибо!

8 ответов

Решение

Вы можете использовать Джексона Миксинса. Например:

class YourClass {
  public int ignoreThis() { return 0; }    
}

С этим миксином

abstract class MixIn {
  @JsonIgnore abstract int ignoreThis(); // we don't need it!  
}

С этим:

objectMapper.getSerializationConfig().addMixInAnnotations(YourClass.class, MixIn.class);

Редактировать:

Благодаря комментариям, с Jackson 2.5+, API изменился и должен вызываться с objectMapper.addMixIn(Class<?> target, Class<?> mixinSource)

Еще одна возможность: если вы хотите игнорировать все неизвестные свойства, вы можете настроить маппер следующим образом:

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Использование Java-класса

new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

Использование аннотации

@JsonIgnoreProperties(ignoreUnknown=true)

Подход, основанный на аннотациях, лучше. Но иногда требуется ручное управление. Для этого вы можете использовать без метода ObjectWriter.

ObjectMapper mapper   = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
ObjectWriter writer   = mapper.writer().withoutAttribute("property1").withoutAttribute("property2");
String       jsonText = writer.writeValueAsString(sourceObject);

Если вы хотите ВСЕГДА исключать определенные свойства для любого класса, вы можете использовать setMixInResolver метод:

    @JsonIgnoreProperties({"id", "index", "version"})
    abstract class MixIn {
    }

    mapper.setMixInResolver(new ClassIntrospector.MixInResolver(){
        @Override
        public Class<?> findMixInClassFor(Class<?> cls) {
            return MixIn.class;  
        }

        @Override
        public ClassIntrospector.MixInResolver copy() {
            return this;
        }
    });

Смешанные аннотации работают довольно хорошо здесь, как уже упоминалось. Другая возможность, выходящая за пределы свойства @JsonIgnore, заключается в использовании @JsonIgnoreType, если у вас есть тип, который никогда не следует включать (т. Е. Если все экземпляры свойств GeometryCollection следует игнорировать). Затем вы можете либо добавить его напрямую (если вы управляете типом), либо использовать дополнение, например:

@JsonIgnoreType abstract class MixIn { }
// and then register mix-in, either via SerializationConfig, or by using SimpleModule

Это может быть более удобно, если у вас есть много классов, у всех из которых есть один метод доступа IgnoredType getContext() или около того (что имеет место для многих платформ)

У меня была похожая проблема, но она была связана с двунаправленными отношениями Hibernate. Я хотел показать одну сторону отношений и программно игнорировать другую, в зависимости от того, с какой точкой зрения я имел дело. Если вы не можете сделать это, вы в конечном итоге с неприятным StackruExceptions. Например, если бы у меня были эти объекты

public class A{
  Long id;
  String name;
  List<B> children;
}

public class B{
  Long id;
  A parent;
}

Я хотел бы программно игнорировать parent поле в B, если я смотрю на A, и игнорировать children поле в А, если я смотрел на Б.

Я начал использовать миксин, чтобы сделать это, но это очень быстро становится ужасным; вокруг вас так много бесполезных классов, которые существуют исключительно для форматирования данных. Я закончил тем, что написал свой собственный сериализатор для более чистой обработки: https://github.com/monitorjbl/json-view.

Это позволяет программно указать, какие поля игнорировать:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(JsonView.class, new JsonViewSerializer());
mapper.registerModule(module);

List<A> list = getListOfA();
String json = mapper.writeValueAsString(JsonView.with(list)
    .onClass(B.class, match()
        .exclude("parent")));

Это также позволяет вам легко указывать очень упрощенные представления с помощью подстановочных знаков:

String json = mapper.writeValueAsString(JsonView.with(list)
    .onClass(A.class, match()
        .exclude("*")
         .include("id", "name")));

В моем первоначальном случае потребность в простых представлениях, подобных этому, заключалась в том, чтобы показать минимальный минимум в отношении родителя / ребенка, но это также стало полезным для нашей безопасности на основе ролей. Менее привилегированные представления объектов необходимы для получения меньшего количества информации об объекте.

Все это исходит от сериализатора, но я использовал Spring MVC в своем приложении. Чтобы он правильно обрабатывал эти случаи, я написал интеграцию, которую вы можете включить в существующие классы контроллера Spring:

@Controller
public class JsonController {
  private JsonResult json = JsonResult.instance();
  @Autowired
  private TestObjectService service;

  @RequestMapping(method = RequestMethod.GET, value = "/bean")
  @ResponseBody
  public List<TestObject> getTestObject() {
    List<TestObject> list = service.list();

    return json.use(JsonView.with(list)
        .onClass(TestObject.class, Match.match()
            .exclude("int1")
            .include("ignoredDirect")))
        .returnValue();
  }
}

Оба доступны на Maven Central. Я надеюсь, что это поможет кому-то еще, это особенно уродливая проблема с Джексоном, у которой не было хорошего решения для моего случая.

public @interface JsonIgnoreProperties

Аннотация, которую можно использовать для подавления сериализации свойств (во время сериализации) или игнорирования обработки чтения свойств JSON (во время десериализации).

для предотвращения сериализации или десериализации указанных полей вы можете использовать:

@JsonIgnoreProperties(ignoreUnknown=true)

Еще один хороший момент здесь заключается в использовании @JsonFilter, Некоторые подробности здесь http://wiki.fasterxml.com/JacksonFeatureJsonFilter

Другие вопросы по тегам