Reputation: 327
So I'm doing students testing system, my first restful web service and I need to get rid off information in JSON responses I don't need to be sent. I know I can use annotations like @JsonIgnore
, but it doesn't fit in my situation because the data I need differentiate in different methods from the same object.
I know there are mappers and mixins, but I don't think it fits here because I need to exclude just one property from the nested object, not the whole object in the object. Maybe there is some simple solution for multiple JSON customizations for different response methods.
I'm using jackson-databind
, spring data
, spring MVC
and also hibernate
.
I need just testName
from testObj
, but can I exclude testOptionsList
? without using @JsonIgnore
?
Or maybe it's my overall API architecture flaw?
Controller:
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
ScoresByTestDao scoreRep;
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public List<ScoreByTest> getScoresListByUserId(@PathVariable int id) {
return scoreRep.getTestScoresByUser(id);
}
Repository:
public interface ScoresByTestDao extends JpaRepository<ScoreByTest, Integer> {
@Query("select s from ScoreByTest s where s.userObj.id = :userId")
List<ScoreByTest> getTestScoresByUser(@Param("userId") int userId);
}
Request response example:
{
id:1,
score:20.1,
givenTestObj:{
id:1,
date:1535749200000,
code:"ABCD123",
testObj:{
id:1,
testName:"Java I test",
testQuestionsList:[
{
id:3,
question:"What is JRE?",
rightChoices:1,
testOptionsList:[
{
id:1,
testOption:"JRE is a java based GUI application.",
correct:false
},
{
id:2,
testOption:"JRE is an application development framework.",
correct:false
},
{
id:3,
testOption:"JRE is an implementation of the Java Virtual Machine which executes Java programs.",
correct:true
},
{
id:4,
testOption:"None of the above.",
correct:false
}
]
},
{
id:4,
question:"Can we compare int variable with a boolean variable?",
rightChoices:1,
testOptionsList:[
{
id:5,
testOption:"True",
correct:false
},
{
id:6,
testOption:"False",
correct:true
}
]
},
{
etc...
What table I want to fill in UI:
+------+------+-------+
|Test |Date |Score |
+------+------+-------+
ScoreByTest class:
@Entity
@Table(name = "scores_by_test")
public class ScoreByTest implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@NotNull
@Column(name = "score")
private float score;
@JoinColumn(name = "id_given_tests", referencedColumnName = "id")
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private GivenTest givenTestObj;
@JoinColumn(name = "id_user", referencedColumnName = "id")
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private User userObj;
public ScoreByTest() {
}
public ScoreByTest(Integer id) {
this.id = id;
}
public ScoreByTest(Integer id, float score) {
this.id = id;
this.score = score;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public float getScore() {
return score;
}
public void setScore(float score) {
this.score = score;
}
public GivenTest getGivenTestObj() {
return givenTestObj;
}
public void setGivenTestsObj(GivenTest givenTestsObj) {
this.givenTestObj = givenTestsObj;
}
public User getUserObj() {
return userObj;
}
public void setUserObj(User userObj) {
this.userObj = userObj;
}
GivenTest class:
@Entity
@Table(name = "given_tests")
public class GivenTest implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@NotNull
@Column(name = "date")
@Temporal(TemporalType.DATE)
private Date date = new Date();
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 50)
@Column(name = "code")
private String code;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "givenTestObj", fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SELECT)
@JsonIgnore
private List<ChosenOption> chosenOptionsList;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "givenTestObj", fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SELECT)
@JsonIgnore
private List<ScoreByTest> scoresByTestList;
@JoinColumn(name = "id_test", referencedColumnName = "id")
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private Test testObj;
public GivenTest() {
}
public GivenTest(Integer id) {
this.id = id;
}
public GivenTest(Integer id, Date date, String code) {
this.id = id;
this.date = date;
this.code = code;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public List<ChosenOption> getChosenOptionsList() {
return chosenOptionsList;
}
public void setChosenOptionsList(List<ChosenOption> chosenOptionsList) {
this.chosenOptionsList = chosenOptionsList;
}
public List<ScoreByTest> getScoresByTestList() {
return scoresByTestList;
}
public void setScoresByTestList(List<ScoreByTest> scoresByTestList) {
this.scoresByTestList = scoresByTestList;
}
public Test getTestObj() {
return testObj;
}
public void setTestObj(Test testObj) {
this.testObj = testObj;
}
TestQuestion class:
@Entity
@Table(name = "test_questions")
public class TestQuestion implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@NotNull
@Lob
@Size(min = 1, max = 65535)
@Column(name = "question")
private String question;
@Basic(optional = false)
@NotNull
@Column(name = "right_choices")
private short rightChoices;
@JoinColumn(name = "id_test", referencedColumnName = "id")
@ManyToOne(optional = false, fetch = FetchType.EAGER)
@JsonIgnore
private Test testObj;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "testQuestionObj", fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SELECT)
private List<TestOption> testOptionsList;
public TestQuestion() {
}
public TestQuestion(Integer id) {
this.id = id;
}
public TestQuestion(Integer id, String question, short rightChoices) {
this.id = id;
this.question = question;
this.rightChoices = rightChoices;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public short getRightChoices() {
return rightChoices;
}
public void setRightChoices(short rightChoices) {
this.rightChoices = rightChoices;
}
public Test getTestObj() {
return testObj;
}
public void setTestObj(Test testObj) {
this.testObj = testObj;
}
public List<TestOption> getTestOptionsList() {
return testOptionsList;
}
public void setTestOptionsList(List<TestOption> testOptionsList) {
this.testOptionsList = testOptionsList;
}
TestOption class:
@Entity
@Table(name = "test_options")
public class TestOption implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@NotNull
@Column(name = "test_option")
private String testOption;
@Basic(optional = false)
@NotNull
@Column(name = "correct")
private boolean correct;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "testOptionObj", fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SELECT)
@JsonIgnore
private List<ChosenOption> chosenOptionsList;
@JoinColumn(name = "id_test_question", referencedColumnName = "id")
@ManyToOne(optional = false, fetch = FetchType.EAGER)
@JsonIgnore
private TestQuestion testQuestionObj;
public TestOption() {
}
public TestOption(Integer id) {
this.id = id;
}
public TestOption(Integer id, String testOption, boolean correct) {
this.id = id;
this.testOption = testOption;
this.correct = correct;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTestOption() {
return testOption;
}
public void setTestOption(String testOption) {
this.testOption = testOption;
}
public boolean getCorrect() {
return correct;
}
public void setCorrect(boolean correct) {
this.correct = correct;
}
public List<ChosenOption> getChosenOptionsList() {
return chosenOptionsList;
}
public void setChosenOptionsList(List<ChosenOption> chosenOptionsList) {
this.chosenOptionsList = chosenOptionsList;
}
public TestQuestion getTestQuestionObj() {
return testQuestionObj;
}
public void setTestQuestionObj(TestQuestion testQuestionObj) {
this.testQuestionObj = testQuestionObj;
}
SQL relations for a simple overview:
https://i.sstatic.net/4Hkcw.jpg
Upvotes: 0
Views: 177
Reputation: 4432
Have you looked into Jackson's @JsonView
? I think it should fit your scenario quite nicely. Here is a simple example. Or if you want to go fully with Spring, then Spring Data REST could be helpful as well - an example.
Upvotes: 1