Как я могу сказать Джексону игнорировать свойство, для которого у меня нет контроля над исходным кодом?
короче говоря, одна из моих сущностей имеет GeometryCollection это вызывает исключение, когда вы называете "getBoundary" (почему это другая книга, а теперь давайте скажем, что это так работает).
есть ли способ, которым я могу сказать Джексону не включать этот конкретный геттер? Я знаю, что могу использовать @JacksonIgnore, когда я владею/контролирую код. Но это не так, Джексон заканчивается, достигая этой точки через непрерывную сериализацию родительских объектов. Я видел опция фильтрации в документации Джексона. Это правдоподобное решение?
спасибо!
8 ответов:
можно использовать Джексон Миксины. Например:
class YourClass { public int ignoreThis() { return 0; } }С этим Mixin
abstract class MixIn { @JsonIgnore abstract int ignoreThis(); // we don't need it! }С этого:
objectMapper.getSerializationConfig().addMixInAnnotations(YourClass.class, MixIn.class);Edit:
благодаря комментариям, с Jackson 2.5+, API изменился и должен быть вызван с
objectMapper.addMixIn(Class<?> target, Class<?> mixinSource)
еще одна возможность заключается в том, что если вы хотите игнорировать все неизвестные свойства, вы можете настроить mapper следующим образом:
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Используя Класс Java
new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)Используя Аннотации
@JsonIgnoreProperties(ignoreUnknown=true)
Mix-in аннотации работают довольно хорошо здесь, как уже упоминалось. Еще одна возможность помимо per-property @JsonIgnore-использовать @JsonIgnoreType, если у вас есть тип, который никогда не должен быть включен (т. е. если все экземпляры свойств GeometryCollection должны игнорироваться). Затем вы можете либо добавить его напрямую (если вы управляете типом), либо использовать mix-in, например:
@JsonIgnoreType abstract class MixIn { } // and then register mix-in, either via SerializationConfig, or by using SimpleModuleЭто может быть более удобно, если у вас есть много классов, которые все имеют один ' IgnoredType getContext()' доступа или так (что имеет место для многих фреймворков)
public @interface JsonIgnorePropertiesаннотация, которая может использоваться либо для подавления сериализации свойств (во время сериализации), либо для игнорирования обработки считанных свойств JSON (во время десериализации).
для предотвращения сериализации или десериализации указанных полей можно использовать:
@JsonIgnoreProperties(ignoreUnknown=true)
у меня была аналогичная проблема, но она была связана с двунаправленными отношениями Hibernate. Я хотел показать одну сторону отношений и программно игнорировать другую, в зависимости от того, с какой точкой зрения я имел дело. Если вы не можете этого сделать, вы в конечном итоге с неприятным
StackOverflowExceptionы. Например, если бы у меня были эти объектыpublic class A{ Long id; String name; List<B> children; } public class B{ Long id; A parent; }Я хотел бы программно игнорировать
parentполе в B, если я смотрел на A, и игнорироватьchildrenполе в A, если бы я смотрел Б.Я начал использовать mixins для этого, но это очень быстро становится ужасно; у вас так много бесполезных классов, которые существуют исключительно для форматирования данных. Я закончил тем, что написал свой собственный сериализатор, чтобы справиться с этим более чистым способом: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. Я надеюсь, что это поможет кому-то еще там, это особенно уродливая проблема с Джексоном, у которого не было хорошего решения для моего случая.
подход на основе аннотаций лучше. Но иногда требуется ручное управление. Для этого вы можете использовать без метод 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);
еще один хороший момент здесь, чтобы использовать
@JsonFilter. Некоторые подробности здесь http://wiki.fasterxml.com/JacksonFeatureJsonFilter
Comments