Using Jackson, how can I serialise the result of a parameterised method call to filter a list of child...





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







2















I'm using SpringBoot / Hibernate for my application framework.
I have a class that holds a load of parameters for my application. It has some parameters that always apply, and some that differ depending on what's being worked on (per-project params). This has been modelled as a Parent class that contains a collection of Child classes, whereby one and only one instance of the children will be 'active' at any one time, depending on some context (e.g. the project being worked on, but the real case has somewhat more complex logic to determine the 'active' child).



In nearly all cases, I only want to serialise the one child that is applicable at the time, but in a few cases, I want to serialise the whole set.



I can achieve it using the following:



public class Parent {

@JsonView(JsonViews.AllChildren.class)
private Set<Child> children= new HashSet<>();

@JsonIgnore
private Context context;

public void setContext (Context context) {
this.context = context;
}

@JsonView(JsonViews.ActiveChild.class)
@JsonProperty("activeChild")
public Child getActiveChild() {

for (Child child : this.children) {
if (someFunction(this.context)) {
return child;
}
}

return null;
}


Then in my controller I can do:



@GetMapping("/parent")
@JsonView(JsonViews.AllChildren.class)
public Parent getParent() {
return ParentService.getParent();
}

@GetMapping("/parent/{context}")
@JsonView(JsonViews.ActiveChild.class)
public Parent getParentWithContext(PathVariable final String contextName)) {
Context context = ContextService.getContextByName(contextName);
Parent parent = ParentService.getParent();
parent.setContext(context);
return Parent;
}


Works nicely, but introduces some state (setting the context on the Parent) that I want to avoid.



So now the question: How can I serialise the Parent / child classes to remove the state attribute, e.g. something like:



@JsonView(JsonViews.ActiveChild.class)
@JsonProperty("activeChild")
public Child getActiveChild(Context context) {

for (Child child : this.children) {
if (someFunction(context)) {
return child;
}
}

return null;
}

@GetMapping("/parent/{context}")
@JsonView(JsonViews.ActiveChild.class)
public Parent getParentWithContext(PathVariable final String contextName)) {
Context context = ContextService.getContextByName(contextName);
Parent parent = ParentService.getParent();

// How to tell the Json serialization to pass the context to getActiveChild

return Parent;
}


Everything I've found about the Json Context serialisation seems to have a fixed set of contexts (mines an unknown list) and be used to add/remove attributes from the output, rather than filtering the data.



The only solution I've found so far is to call ObjectMapper myself to get a full json serialisation of all the children, then remove all but the one I want to return. But doing that means I have duplicate sets of "Which child is active for this context" logic - one within the Parent class the works with the Parent and Child objects, and one in the getParentWithContext function that works with the json representation. Is there anything better I can do, e.g.




  1. Do some custom serialiser that can somehow call the getActiveChild method on the parent with the passed context before rendering the result, or

  2. Somehow make the context ThreadLocal when it's set in the rendering call?

  3. Somehow create a new class that extends my Parent class with the Context class instance in its constructor and return that for Jackson to serialize?

  4. Create a clone of the Parent, set the context on the clone, let that be serialised then garbage-collected when done?










share|improve this question































    2















    I'm using SpringBoot / Hibernate for my application framework.
    I have a class that holds a load of parameters for my application. It has some parameters that always apply, and some that differ depending on what's being worked on (per-project params). This has been modelled as a Parent class that contains a collection of Child classes, whereby one and only one instance of the children will be 'active' at any one time, depending on some context (e.g. the project being worked on, but the real case has somewhat more complex logic to determine the 'active' child).



    In nearly all cases, I only want to serialise the one child that is applicable at the time, but in a few cases, I want to serialise the whole set.



    I can achieve it using the following:



    public class Parent {

    @JsonView(JsonViews.AllChildren.class)
    private Set<Child> children= new HashSet<>();

    @JsonIgnore
    private Context context;

    public void setContext (Context context) {
    this.context = context;
    }

    @JsonView(JsonViews.ActiveChild.class)
    @JsonProperty("activeChild")
    public Child getActiveChild() {

    for (Child child : this.children) {
    if (someFunction(this.context)) {
    return child;
    }
    }

    return null;
    }


    Then in my controller I can do:



    @GetMapping("/parent")
    @JsonView(JsonViews.AllChildren.class)
    public Parent getParent() {
    return ParentService.getParent();
    }

    @GetMapping("/parent/{context}")
    @JsonView(JsonViews.ActiveChild.class)
    public Parent getParentWithContext(PathVariable final String contextName)) {
    Context context = ContextService.getContextByName(contextName);
    Parent parent = ParentService.getParent();
    parent.setContext(context);
    return Parent;
    }


    Works nicely, but introduces some state (setting the context on the Parent) that I want to avoid.



    So now the question: How can I serialise the Parent / child classes to remove the state attribute, e.g. something like:



    @JsonView(JsonViews.ActiveChild.class)
    @JsonProperty("activeChild")
    public Child getActiveChild(Context context) {

    for (Child child : this.children) {
    if (someFunction(context)) {
    return child;
    }
    }

    return null;
    }

    @GetMapping("/parent/{context}")
    @JsonView(JsonViews.ActiveChild.class)
    public Parent getParentWithContext(PathVariable final String contextName)) {
    Context context = ContextService.getContextByName(contextName);
    Parent parent = ParentService.getParent();

    // How to tell the Json serialization to pass the context to getActiveChild

    return Parent;
    }


    Everything I've found about the Json Context serialisation seems to have a fixed set of contexts (mines an unknown list) and be used to add/remove attributes from the output, rather than filtering the data.



    The only solution I've found so far is to call ObjectMapper myself to get a full json serialisation of all the children, then remove all but the one I want to return. But doing that means I have duplicate sets of "Which child is active for this context" logic - one within the Parent class the works with the Parent and Child objects, and one in the getParentWithContext function that works with the json representation. Is there anything better I can do, e.g.




    1. Do some custom serialiser that can somehow call the getActiveChild method on the parent with the passed context before rendering the result, or

    2. Somehow make the context ThreadLocal when it's set in the rendering call?

    3. Somehow create a new class that extends my Parent class with the Context class instance in its constructor and return that for Jackson to serialize?

    4. Create a clone of the Parent, set the context on the clone, let that be serialised then garbage-collected when done?










    share|improve this question



























      2












      2








      2








      I'm using SpringBoot / Hibernate for my application framework.
      I have a class that holds a load of parameters for my application. It has some parameters that always apply, and some that differ depending on what's being worked on (per-project params). This has been modelled as a Parent class that contains a collection of Child classes, whereby one and only one instance of the children will be 'active' at any one time, depending on some context (e.g. the project being worked on, but the real case has somewhat more complex logic to determine the 'active' child).



      In nearly all cases, I only want to serialise the one child that is applicable at the time, but in a few cases, I want to serialise the whole set.



      I can achieve it using the following:



      public class Parent {

      @JsonView(JsonViews.AllChildren.class)
      private Set<Child> children= new HashSet<>();

      @JsonIgnore
      private Context context;

      public void setContext (Context context) {
      this.context = context;
      }

      @JsonView(JsonViews.ActiveChild.class)
      @JsonProperty("activeChild")
      public Child getActiveChild() {

      for (Child child : this.children) {
      if (someFunction(this.context)) {
      return child;
      }
      }

      return null;
      }


      Then in my controller I can do:



      @GetMapping("/parent")
      @JsonView(JsonViews.AllChildren.class)
      public Parent getParent() {
      return ParentService.getParent();
      }

      @GetMapping("/parent/{context}")
      @JsonView(JsonViews.ActiveChild.class)
      public Parent getParentWithContext(PathVariable final String contextName)) {
      Context context = ContextService.getContextByName(contextName);
      Parent parent = ParentService.getParent();
      parent.setContext(context);
      return Parent;
      }


      Works nicely, but introduces some state (setting the context on the Parent) that I want to avoid.



      So now the question: How can I serialise the Parent / child classes to remove the state attribute, e.g. something like:



      @JsonView(JsonViews.ActiveChild.class)
      @JsonProperty("activeChild")
      public Child getActiveChild(Context context) {

      for (Child child : this.children) {
      if (someFunction(context)) {
      return child;
      }
      }

      return null;
      }

      @GetMapping("/parent/{context}")
      @JsonView(JsonViews.ActiveChild.class)
      public Parent getParentWithContext(PathVariable final String contextName)) {
      Context context = ContextService.getContextByName(contextName);
      Parent parent = ParentService.getParent();

      // How to tell the Json serialization to pass the context to getActiveChild

      return Parent;
      }


      Everything I've found about the Json Context serialisation seems to have a fixed set of contexts (mines an unknown list) and be used to add/remove attributes from the output, rather than filtering the data.



      The only solution I've found so far is to call ObjectMapper myself to get a full json serialisation of all the children, then remove all but the one I want to return. But doing that means I have duplicate sets of "Which child is active for this context" logic - one within the Parent class the works with the Parent and Child objects, and one in the getParentWithContext function that works with the json representation. Is there anything better I can do, e.g.




      1. Do some custom serialiser that can somehow call the getActiveChild method on the parent with the passed context before rendering the result, or

      2. Somehow make the context ThreadLocal when it's set in the rendering call?

      3. Somehow create a new class that extends my Parent class with the Context class instance in its constructor and return that for Jackson to serialize?

      4. Create a clone of the Parent, set the context on the clone, let that be serialised then garbage-collected when done?










      share|improve this question
















      I'm using SpringBoot / Hibernate for my application framework.
      I have a class that holds a load of parameters for my application. It has some parameters that always apply, and some that differ depending on what's being worked on (per-project params). This has been modelled as a Parent class that contains a collection of Child classes, whereby one and only one instance of the children will be 'active' at any one time, depending on some context (e.g. the project being worked on, but the real case has somewhat more complex logic to determine the 'active' child).



      In nearly all cases, I only want to serialise the one child that is applicable at the time, but in a few cases, I want to serialise the whole set.



      I can achieve it using the following:



      public class Parent {

      @JsonView(JsonViews.AllChildren.class)
      private Set<Child> children= new HashSet<>();

      @JsonIgnore
      private Context context;

      public void setContext (Context context) {
      this.context = context;
      }

      @JsonView(JsonViews.ActiveChild.class)
      @JsonProperty("activeChild")
      public Child getActiveChild() {

      for (Child child : this.children) {
      if (someFunction(this.context)) {
      return child;
      }
      }

      return null;
      }


      Then in my controller I can do:



      @GetMapping("/parent")
      @JsonView(JsonViews.AllChildren.class)
      public Parent getParent() {
      return ParentService.getParent();
      }

      @GetMapping("/parent/{context}")
      @JsonView(JsonViews.ActiveChild.class)
      public Parent getParentWithContext(PathVariable final String contextName)) {
      Context context = ContextService.getContextByName(contextName);
      Parent parent = ParentService.getParent();
      parent.setContext(context);
      return Parent;
      }


      Works nicely, but introduces some state (setting the context on the Parent) that I want to avoid.



      So now the question: How can I serialise the Parent / child classes to remove the state attribute, e.g. something like:



      @JsonView(JsonViews.ActiveChild.class)
      @JsonProperty("activeChild")
      public Child getActiveChild(Context context) {

      for (Child child : this.children) {
      if (someFunction(context)) {
      return child;
      }
      }

      return null;
      }

      @GetMapping("/parent/{context}")
      @JsonView(JsonViews.ActiveChild.class)
      public Parent getParentWithContext(PathVariable final String contextName)) {
      Context context = ContextService.getContextByName(contextName);
      Parent parent = ParentService.getParent();

      // How to tell the Json serialization to pass the context to getActiveChild

      return Parent;
      }


      Everything I've found about the Json Context serialisation seems to have a fixed set of contexts (mines an unknown list) and be used to add/remove attributes from the output, rather than filtering the data.



      The only solution I've found so far is to call ObjectMapper myself to get a full json serialisation of all the children, then remove all but the one I want to return. But doing that means I have duplicate sets of "Which child is active for this context" logic - one within the Parent class the works with the Parent and Child objects, and one in the getParentWithContext function that works with the json representation. Is there anything better I can do, e.g.




      1. Do some custom serialiser that can somehow call the getActiveChild method on the parent with the passed context before rendering the result, or

      2. Somehow make the context ThreadLocal when it's set in the rendering call?

      3. Somehow create a new class that extends my Parent class with the Context class instance in its constructor and return that for Jackson to serialize?

      4. Create a clone of the Parent, set the context on the clone, let that be serialised then garbage-collected when done?







      java json jackson






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 17 '18 at 23:38







      S Bullen

















      asked Nov 16 '18 at 23:19









      S BullenS Bullen

      113




      113
























          0






          active

          oldest

          votes












          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53346623%2fusing-jackson-how-can-i-serialise-the-result-of-a-parameterised-method-call-to%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53346623%2fusing-jackson-how-can-i-serialise-the-result-of-a-parameterised-method-call-to%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Xamarin.iOS Cant Deploy on Iphone

          Glorious Revolution

          Dulmage-Mendelsohn matrix decomposition in Python