{"id":2434,"date":"2020-02-23T21:02:34","date_gmt":"2020-02-23T21:02:34","guid":{"rendered":"http:\/\/www.andygibson.net\/blog\/?p=2434"},"modified":"2020-02-23T21:04:05","modified_gmt":"2020-02-23T21:04:05","slug":"inherited-jackson-serializers","status":"publish","type":"post","link":"http:\/\/www.andygibson.net\/blog\/article\/inherited-jackson-serializers\/","title":{"rendered":"Inherited Jackson Serializers"},"content":{"rendered":"\n<p>Looking at the <a rel=\"noreferrer noopener\" aria-label=\"Jackson Serializer (opens in a new tab)\" href=\"http:\/\/www.andygibson.net\/blog\/article\/introduction-to-jackson-serializers\/\" target=\"_blank\">Jackson Serializer<\/a> post, it does introduce a particular code smell as it uses <code>if<\/code> statements to check the type of object and take a different action based on that type. Normally, that is indicative of the need to implement the action in the class and\/or subclasses. However, this is serialization and we certainly don&#8217;t want to put any serialization code in the model classes themselves. This article looks at getting rid of that code smell using inheritance with serializers. The source code is available in my <a href=\"https:\/\/github.com\/andygibson\/blog-post-code\/tree\/master\/java\/inherited-jackson-serializers\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"blog post code repository (opens in a new tab)\">blog post code repository<\/a>.<\/p>\n\n\n\n<p>We can create a class hierarchy of serializers that makes use of inheritance to replace a set of if\/then statements based on the object type. In this post, we&#8217;ll implement serializers that are inherited for the different Pet types and ensure that the serialization of each Pet type of encapsulated in its own serializer.<\/p>\n\n\n\n<p>One problem is that the execution of overridden implementations  is sequential, we would execute the implementation in the parent class, then the first subclass, and then any further subclasses. Since our top level implementation likely consists of :<\/p>\n\n\n\n<ul><li>Start writing an object &#8220;{&#8220;<\/li><li>Write Object properties  &#8220;x = 1&#8221;<\/li><li>End writing an object &#8220;}&#8221;<\/li><\/ul>\n\n\n\n<p>If we subclass the serializer and override the <code>serialize()<\/code> method and call the parent implementation, in JSON we will open the object, close it, and then write any subclass properties. We want to open the object, write all of the properties, including subclass properties, and then close the object.<\/p>\n\n\n\n<h3>Template Method<\/h3>\n\n\n\n<p>We can solve this problem using a <a rel=\"noreferrer noopener\" aria-label=\"template method (opens in a new tab)\" href=\"https:\/\/en.wikipedia.org\/wiki\/Template_method_pattern\" target=\"_blank\">template method<\/a> which is invoked during the execution of an algorithm, and provides options to extend the algorithm while maintaining the main structure of it.  This is a good technique to use when you want to maintain a rigid list of actions, but allow one of those actions to be overridden and extended.<\/p>\n\n\n\n<p>We&#8217;ll create an <code>ObjectSerializer<\/code> class that is used as the base class for our serializers. This class expects subclasses to be used to serialize objects.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic abstract class ObjectSerializer&lt;T&gt; extends StdSerializer&lt;T&gt; {\n\n  public ObjectSerializer(final Class&lt;T&gt; t) {\n    super(t);\n  }\n\n  @Override\n  public void serialize(final T value, final JsonGenerator gen, final SerializerProvider provider) throws IOException {\n    gen.writeStartObject();\n    doWriteProperties(value, gen, provider);\n    gen.writeEndObject();\n  }\n\n  protected abstract void doWriteProperties(final T value, final JsonGenerator gen, final SerializerProvider provider);\n}\n\n<\/pre><\/div>\n\n\n<p>Our <code>serialize<\/code> method starts a new object, invokes the call to write the object properties, and then ends the object. Any properties written in the <code>doWriteProperties<\/code> method will sit inside the JSON object.<\/p>\n\n\n\n<p>Our PetSerializer won&#8217;t write any Pet, but could just write the common properties for the Pet object :<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class PetSerializer&lt;T extends Pet&gt; extends ObjectSerializer&lt;T&gt; {\n  public PetSerializer(final Class&lt;T&gt; clazz) {\n    super(clazz);\n  }\n\n  @Override\n  protected void doWriteProperties(final T value, final JsonGenerator gen, final SerializerProvider provider)\n      throws IOException {\n    \/\/ this could go in the subclass serializer if a more calculated value was needed.\n    gen.writeStringField(&quot;type&quot;, value.getClass().getSimpleName());\n    gen.writeStringField(&quot;name&quot;, value.getName());\n  }\n}\n\n<\/pre><\/div>\n\n\n<p>Here we override the <code>doWriteProperties<\/code> method to write the type and the name, the two common values of the Pet type that need serializing. Note that we also enhanced the generic type to ensure that we only use this on subtypes of <code>Pet<\/code>.<\/p>\n\n\n\n<p>We can now subclass this serializer for each of our Pet types :<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class DogSerializer extends PetSerializer&lt;Dog&gt; {\n  public DogSerializer() {\n    super(Dog.class);\n  }\n  @Override\n  protected void doWriteProperties(final Dog value, final JsonGenerator gen, final SerializerProvider provider)\n      throws IOException {\n    super.doWriteProperties(value, gen, provider);\n    gen.writeStringField(&quot;size&quot;, value.getSize().toString());\n  }\n}\n<\/pre><\/div>\n\n\n<p>and <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class SnakeSerializer extends PetSerializer&lt;Snake&gt; {\n\n  public SnakeSerializer() {\n    super(Snake.class);\n  }\n\n  @Override\n  protected void doWriteProperties(final Snake value, final JsonGenerator gen, final SerializerProvider provider)\n      throws IOException {\n    super.doWriteProperties(value, gen, provider);\n    gen.writeNumberField(&quot;length&quot;, value.getLength());\n  }\n}\n\n<\/pre><\/div>\n\n\n<p>We have implemented the PetSerializer for our two classes and override the <code>doWriteProperties<\/code> method to write properties specific to that Pet. <\/p>\n\n\n\n<p>To use our new serializers, we just need to register them with the Jackson <code>Module<\/code> in our main code. Note that we no longer need to register the <code>Pet<\/code> serializer since it is never used directly, only from their subclasses. We do however have to register the serializers for the <code>Dog<\/code> and <code>Snake<\/code> classes.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class Main {\n\n  public static void main(final String&#91;] args) throws JsonProcessingException {\n    final ObjectMapper objectMapper = new ObjectMapper();\n    final SimpleModule module = new SimpleModule(&quot;mySerializers&quot;);\n    module.addSerializer(new PersonSerializer());\n    module.addSerializer(new DogSerializer());\n    module.addSerializer(new SnakeSerializer());\n    objectMapper.registerModule(module);\n    ...\n    ...\n  }\n}\n<\/pre><\/div>\n\n\n<p>The rest of the code to create the model and write it to JSON will now still work with the new serializers used to write the objects. While this does get rid of the code smell mentioned originally, technically, it is only moving it to a hidden location. Jackson still does some kind of lookup for the class to determine what serializer it should use instead of a set of <code>if<\/code> statements to locate the matching serializer.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Looking at the Jackson Serializer post, it does introduce a particular code smell as it uses if statements to check the type of object and take a different action based on that type. Normally, that is indicative of the need to implement the action in the class and\/or subclasses. However, this is serialization and we [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[63],"tags":[134,6,133],"_links":{"self":[{"href":"http:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/posts\/2434"}],"collection":[{"href":"http:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/comments?post=2434"}],"version-history":[{"count":5,"href":"http:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/posts\/2434\/revisions"}],"predecessor-version":[{"id":2439,"href":"http:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/posts\/2434\/revisions\/2439"}],"wp:attachment":[{"href":"http:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/media?parent=2434"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/categories?post=2434"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/tags?post=2434"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}