title: What is the best way to do inline serialization of JSON data using JACKSON?
body: <p>I've got a bean defined as such :</p>
  
  <pre class="lang-java prettyprint-override"><code>public static class TestBean {
      private String a;
      private Long b;
  
      public TestBean(String a, Long b) {
          this.a = a;
          this.b = b;
      }
  
      public String getA() {
          return a;
      }
  
      public Long getB() {
          return b;
      }
  
  }
  </code></pre>
  
  <p>It models some business and I do not get to instantiate it (using JPA). Some of my API let the user retrieve a view of this bean serialize as JSON using Jackson (through JAX-RS) and I would like to add a list of related links to this view.</p>
  
  <p>The normal Jackson JSON serialization would be (for a = "aa" and b = 2L) :</p>
  
  <pre><code>{"a":"aa","b":2}
  </code></pre>
  
  <p>And I would like to have the links appear as </p>
  
  <pre><code>{"a":"aa","b":2,
   "links":[{"rel":"rel","href":"href://"},{"rel":"rel2","href":"href://2"}]}
  </code></pre>
  
  <h2>Possible work-around</h2>
  
  <p>I would rather not add a getLinks() method to my bean, it's specific to this view.</p>
  
  <p>Simply using a composite object would yield a serialization like :</p>
  
  <pre><code>{"data":{"a":"aa","b":2},"links":[{"rel":"rel","href":"href://"}]}
  </code></pre>
  
  <p>Which I could live with but is not what I was looking for ultimately.</p>
  
  <h2>Current solution</h2>
  
  <p>I would like to avoid manipulating the JSON string or having to reload it into a Map to insert my extra values. For now the solution I've come up with seem awfully convoluted:</p>
  
  <p>Current scary solution :</p>
  
  <pre class="lang-java prettyprint-override"><code>//a composite view object
  public abstract class AddedLinksView&lt;K&gt; {
  
      private final K resource;
  
      private final Link[] links;
  
      public AddedLinksView(K resource) {
          this.resource = resource;
          links = buildLinks(resource);
  
      }
  
      public abstract Link[] buildLinks(K resource);
  
      public K getResource() {
          return resource;
      }
  
      public Link[] getLinks() {
          return links;
      }
  
  }
  
  //a specific bean serializer
  private static class RawBeanSerializer extends BeanSerializer {
  
      public RawBeanSerializer(BeanSerializerBase ser) {
          super(ser);
      }
  
      //this is like the standard serialize but without the start and end tags
      public void rawSerialize(Object bean, JsonGenerator jgen, SerializerProvider provider) throws IOException,
              JsonGenerationException {
          if (_propertyFilterId != null) {
              serializeFieldsFiltered(bean, jgen, provider);
          } else {
              serializeFields(bean, jgen, provider);
          }
      }
  
  }
  
  @Test
  public void usingModule() throws Exception {
      // basic module metadata just includes name and version (both for troubleshooting; but name needs to be unique)
      SimpleModule module = new SimpleModule("EnhancedDatesModule", new Version(0, 1, 0, "alpha"));
      //adding a serializer for the composite view
      module.addSerializer(new JsonSerializer&lt;AddedLinksView&gt;() {
  
          @Override
          public Class&lt;AddedLinksView&gt; handledType() {
              return AddedLinksView.class;
          }
  
          @Override
          public void serialize(AddedLinksView value, JsonGenerator jgen, SerializerProvider provider)
                  throws IOException, JsonProcessingException {
              jgen.writeStartObject();
              //looking up the bean serializer that will be used for my resource
              JsonSerializer&lt;Object&gt; ser = provider.findTypedValueSerializer(value.getResource().getClass(), true,
                      null);
  
              if (ser instanceof BeanSerializerBase) {
                  //cloning it in a sub class that makes it possible to 'inline' the serialization
                  RawBeanSerializer openSer = new RawBeanSerializer((BeanSerializerBase) ser);
                  openSer.rawSerialize(value.getResource(), jgen, provider);
              }
              //adding my links
              jgen.writeArrayFieldStart("links");
              for (Link link : value.getLinks()) {
                  jgen.writeObject(link);
              }
              jgen.writeEndArray();
              jgen.writeEndObject();
          }
  
      });
  
      ObjectMapper mapper = new ObjectMapper();
      mapper.registerModule(module);
  
      AddedLinksView&lt;TestBean&gt; view = new AddedLinksView&lt;TestBean&gt;(new TestBean("aa", 2L)) {
          @Override
          public Link[] buildLinks(TestBean resource) {
              return new Link[] { new Link("rel", "href://"), new Link("rel2", "href://2") };
          }
  
      };
  
      System.out.println("useModule json output: " + mapper.writeValueAsString(view));
  }
  </code></pre>
  
  <p>Did I miss something obvious in Jackson to achieve this? Or am I completely off the mark in my requirements already?</p>