{"id":2293,"date":"2017-02-08T09:51:41","date_gmt":"2017-02-08T07:51:41","guid":{"rendered":"http:\/\/hasselba.ch\/blog\/?p=2293"},"modified":"2017-02-15T20:51:46","modified_gmt":"2017-02-15T18:51:46","slug":"jackson-skip-objects-conditionally","status":"publish","type":"post","link":"https:\/\/hasselba.ch\/blog\/?p=2293","title":{"rendered":"Jackson: Skip Objects conditionally"},"content":{"rendered":"<p>I had a simple problem when implementing <a href=\"http:\/\/www.baeldung.com\/jackson-serialize-field-custom-criteria\" target=\"_blank\">this brilliant<\/a> solution in one of my REST applications: As soon I was using <em>@JsonAnyGetter<\/em> \/ <em>@JsonAnySetter<\/em> and the <em>HidableSerializer<\/em> together, a NPE was thrown during serialization. The Problem occured in Jackson 1.9.13 and even 2.5.0, the latest version usable with the actual Domino JVM.<\/p>\n<ul>\n<li><strong>Stack Trace<\/strong><\/li>\n<\/ul>\n<pre class=\"lang-java prettyprint prettyprinted\"><code><span class=\"pln\">org.codehaus.jackson.map.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: ch.hasselba.Test[\"[anySetter]\"])\r\nnull\r\n\u00a0\u00a0\u00a0 at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218)\r\n\u00a0\u00a0\u00a0 at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183)\r\n\u00a0\u00a0\u00a0 at org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140)\r\n\u00a0\u00a0\u00a0 at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158)\r\n\u00a0\u00a0\u00a0 at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)\r\nat ch.hasselba.HidableSerializer.serialize(HidableSerializer.java:29)\r\n\u00a0\u00a0\u00a0 at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610)\r\n\u00a0\u00a0\u00a0 at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)\r\n\u00a0\u00a0\u00a0 at org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapper.java:2575)\r\n\u00a0\u00a0\u00a0 at org.codehaus.jackson.map.ObjectMapper.writeValueAsString(ObjectMapper.java:2097)\r\n\u00a0\u00a0\u00a0 at ch.hasselba.Demo.main(Demo.java:54)\r\nCaused by: java.lang.NullPointerException\r\n\u00a0\u00a0\u00a0 at org.codehaus.jackson.map.ser.std.MapSerializer.serializeFields(MapSerializer.java:243)\r\n\u00a0\u00a0\u00a0 at org.codehaus.jackson.map.ser.AnyGetterWriter.getAndSerialize(AnyGetterWriter.java:41)\r\n\u00a0\u00a0\u00a0 at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:154)\r\n\u00a0\u00a0\u00a0 ... 7 more<\/span><\/code><\/pre>\n<p>After hours of investigation, a simple solution came up on <a href=\"http:\/\/stackoverflow.com\/questions\/41890497\/jackson-jsonanysetter-nullpointer-exception-during-serialization-deserializat\" target=\"_blank\">SO<\/a>: The default serializer must be resolved, and then the code will work. I just had to override resolve method of my <em>HidableSerializer<\/em>:<\/p>\n<pre class=\"lang-java prettyprint prettyprinted\"><code><span class=\"pun\">@Override\r\npublic void resolve(SerializerProvider serializerProvider) throws JsonMappingException {\r\n\u00a0\u00a0\u00a0 if(defaultSerializer instanceof ResolvableSerializer) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ((ResolvableSerializer)defaultSerializer).resolve(serializerProvider);\r\n\u00a0\u00a0\u00a0 }\r\n}<\/span><\/code><\/pre>\n<p>Here is a complete working example:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li><strong>The Demo Code<\/strong><\/li>\n<\/ul>\n<pre class=\"lang-java prettyprint prettyprinted\"><code><span class=\"kwd\">package ch.hasselba;\r\n\r\nimport org.codehaus.jackson.Version;\r\nimport org.codehaus.jackson.map.JsonSerializer;\r\nimport org.codehaus.jackson.map.ObjectMapper;\r\nimport org.codehaus.jackson.map.SerializationConfig;\r\nimport org.codehaus.jackson.map.introspect.BasicBeanDescription;\r\nimport org.codehaus.jackson.map.module.SimpleModule;\r\nimport org.codehaus.jackson.map.ser.BeanSerializerModifier;\r\n\r\npublic class Demo {\r\n\r\n\u00a0\u00a0\u00a0 public static void main(String[] args) {\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ObjectMapper mapper = new ObjectMapper();\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ register the module\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Version version = new Version(1, 0, 0, \"SNAPSHOT\");\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 mapper.registerModule(new SimpleModule(\"HidableModule\", version) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @Override\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public void setupModule(SetupContext context) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 super.setupModule(context);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 context.addBeanSerializerModifier(new BeanSerializerModifier() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @SuppressWarnings(\"unchecked\")\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 @Override\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public JsonSerializer&lt;?&gt; modifySerializer(SerializationConfig config, BasicBeanDescription desc,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 JsonSerializer&lt;?&gt; serializer) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (IHidable.class.isAssignableFrom(desc.getBeanClass())) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return new HidableSerializer&lt;Object&gt;((JsonSerializer&lt;Object&gt;) serializer);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return serializer;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 });\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 });\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ the data\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 String content = \"{ \\\"foo\\\": \\\"bar\\\" }\";\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ build the Object\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Test test = null;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 try {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 test =\u00a0 mapper.readValue(content, Test.class);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } catch (Exception e) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 e.printStackTrace();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ and now convert it back to a String\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 String data = null;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 try {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 data = mapper.writeValueAsString(test);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } catch (Exception e) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 e.printStackTrace();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 System.out.println( data );\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\n}<\/span>\r\n<\/code><\/pre>\n<p>&nbsp;<\/p>\n<ul>\n<li><strong>Test Class<\/strong><\/li>\n<\/ul>\n<pre class=\"lang-java prettyprint prettyprinted\"><code><span class=\"pln\">package ch.hasselba;\r\n\r\nimport java.util.Map;\r\nimport java.util.concurrent.ConcurrentHashMap;\r\n\r\nimport org.codehaus.jackson.annotate.JsonAnyGetter;\r\nimport org.codehaus.jackson.annotate.JsonAnySetter;\r\n\r\npublic class Test implements IHidable {\r\n\r\n\u00a0\u00a0\u00a0 private Map&lt;String, Object&gt; others = new ConcurrentHashMap&lt;String, Object&gt;();\r\n\r\n\u00a0\u00a0\u00a0 @JsonAnyGetter\r\n\u00a0\u00a0\u00a0 public Map&lt;String, Object&gt; getOthers() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return this.others;\r\n\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0 @JsonAnySetter\r\n\u00a0\u00a0\u00a0 public void addOther(final String name, final Object value) {\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 this.others.put(name, value);\r\n\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0 @Override\r\n\u00a0\u00a0\u00a0 public boolean isHidden() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return false;\r\n\u00a0\u00a0\u00a0 }\r\n\r\n}<\/span><\/code><\/pre>\n<p>&nbsp;<\/p>\n<ul>\n<li><strong>Hideable Serializer<\/strong><\/li>\n<\/ul>\n<pre class=\"lang-java prettyprint prettyprinted\"><code><span class=\"pun\">package ch.hasselba;\r\n\r\nimport java.io.IOException;\r\n\r\nimport org.codehaus.jackson.JsonGenerator;\r\nimport org.codehaus.jackson.JsonProcessingException;\r\nimport org.codehaus.jackson.map.JsonSerializer;\r\nimport org.codehaus.jackson.map.SerializerProvider;\r\n\r\npublic class HidableSerializer&lt;T&gt; extends JsonSerializer&lt;T&gt; \u00a0implements ResolvableSerializer {\r\n\r\n\u00a0\u00a0\u00a0 private JsonSerializer&lt;T&gt; defaultSerializer;\r\n\r\n\u00a0\u00a0\u00a0 public HidableSerializer(JsonSerializer&lt;T&gt; serializer) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 defaultSerializer = serializer;\r\n\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0 @Override\r\n\u00a0\u00a0\u00a0 public void serialize(T value, JsonGenerator jgen, SerializerProvider provider)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 throws IOException, JsonProcessingException {\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if( value instanceof IHidable ){\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 IHidable hidableValue = (IHidable) value;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if( hidableValue.isHidden() )\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 defaultSerializer.serialize(value, jgen, provider);\r\n\u00a0\u00a0\u00a0 }\r\n\r\n   @Override\r\n   public void resolve(SerializerProvider serializerProvider) throws JsonMappingException {\r\n\u00a0\u00a0\u00a0    if(defaultSerializer instanceof ResolvableSerializer) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    ((ResolvableSerializer)defaultSerializer).resolve(serializerProvider);\r\n\u00a0\u00a0\u00a0    }\r\n   }\r\n}<\/span><\/code><\/pre>\n<p>&nbsp;<\/p>\n<ul>\n<li><strong>IHidable Interface<\/strong><\/li>\n<\/ul>\n<pre class=\"lang-java prettyprint prettyprinted\"><code><span class=\"kwd\">package<\/span><span class=\"pln\"> ch<\/span><span class=\"pun\">.<\/span><span class=\"pln\">hasselba<\/span><span class=\"pun\">;<\/span>\r\n\r\n<span class=\"kwd\">public<\/span> <span class=\"kwd\">interface<\/span> <span class=\"typ\">IHidable<\/span> <span class=\"pun\">{<\/span>\r\n    <span class=\"kwd\">boolean<\/span><span class=\"pln\"> isHidden<\/span><span class=\"pun\">();<\/span>\r\n<span class=\"pun\">}<\/span><\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I had a simple problem when implementing this brilliant solution in one of my REST applications: As soon I was using @JsonAnyGetter \/ @JsonAnySetter and the HidableSerializer together, a NPE was thrown during serialization. The Problem occured in Jackson 1.9.13 &hellip; <a href=\"https:\/\/hasselba.ch\/blog\/?p=2293\">Weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[114,61],"tags":[7,115,31,60,12],"class_list":["post-2293","post","type-post","status-publish","format-standard","hentry","category-jackson","category-rest","tag-domino","tag-jackson","tag-java","tag-rest","tag-web"],"_links":{"self":[{"href":"https:\/\/hasselba.ch\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2293","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hasselba.ch\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hasselba.ch\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hasselba.ch\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hasselba.ch\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2293"}],"version-history":[{"count":2,"href":"https:\/\/hasselba.ch\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2293\/revisions"}],"predecessor-version":[{"id":2296,"href":"https:\/\/hasselba.ch\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2293\/revisions\/2296"}],"wp:attachment":[{"href":"https:\/\/hasselba.ch\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2293"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hasselba.ch\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2293"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hasselba.ch\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2293"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}