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;
}
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.
- Do some custom serialiser that can somehow call the getActiveChild method on the parent with the passed context before rendering the result, or
- Somehow make the context ThreadLocal when it's set in the rendering call?
- 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?
- Create a clone of the Parent, set the context on the clone, let that be serialised then garbage-collected when done?
java json jackson
add a comment |
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.
- Do some custom serialiser that can somehow call the getActiveChild method on the parent with the passed context before rendering the result, or
- Somehow make the context ThreadLocal when it's set in the rendering call?
- 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?
- Create a clone of the Parent, set the context on the clone, let that be serialised then garbage-collected when done?
java json jackson
add a comment |
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.
- Do some custom serialiser that can somehow call the getActiveChild method on the parent with the passed context before rendering the result, or
- Somehow make the context ThreadLocal when it's set in the rendering call?
- 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?
- Create a clone of the Parent, set the context on the clone, let that be serialised then garbage-collected when done?
java json jackson
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.
- Do some custom serialiser that can somehow call the getActiveChild method on the parent with the passed context before rendering the result, or
- Somehow make the context ThreadLocal when it's set in the rendering call?
- 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?
- Create a clone of the Parent, set the context on the clone, let that be serialised then garbage-collected when done?
java json jackson
java json jackson
edited Nov 17 '18 at 23:38
S Bullen
asked Nov 16 '18 at 23:19
S BullenS Bullen
113
113
add a comment |
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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