0

[Solved! Solution reflected in code]

I'm working on a project with Spring Boot where I need Arrays that contain groups of objects in JSON. It should look like this example:

{  
  "Spring20": [
    {
      "CSCXXX": "Machine Learning",
       . . . 
    },
    {
      "CSCXXX": "Computer Vision",
       . . . 
    }
  ],  

  "Fall20": [
    {
      "EEXXX": "Electronics",
       . . . 
    }
  ]
}

I tried using a Map that stores a String for the Array subject name and a List to hold all of the class objects. This is located in the service class.

 HashMap<String, List<Courses>> courseList = new HashMap<String, List<Courses>>();

[MODIFIED TO FIT SOLUTION]

Service

  public void add( Map<String, List<Courses>> course) {
        course.forEach((string, list) -> {
             if(course_list.containsKey(semester)) {
                course_list.get(semester).addAll(course);
            } else {
                course_list.put(semester, course);
            }
        });  
    }
    public void edit(String semester, String id, Courses courses) {
          // Get the Course list from the Map
          List<Courses> updatedCourse = course_list.get(semester);
          // Loop and find the matching object within the list
          for(int i=0; i<updatedCourse.size(); i++){
            if (updatedCourse.get(i).getID().equals(id)){
                // Once object found, update its values in the list 
                updatedCourse.get(i).set(course.getSubject())
                . . .
                // Finally, replace the list within the map
                course_list.replace(semester,  updatedCourse);
            }
        }
    }

Controller

    @RequestMapping(method=RequestMethod.POST, value="/add")
    public void addCourse(@RequestBody Map<String, List<Courses>> course) {
        service.addTest(course);
    }

    @RequestMapping(method=RequestMethod.PUT, value="/edit/{semster}/{id}")
    public void addCourse(@PathVariable("semester") String semester, @PathVariable("id") String id, @RequestBody Courses course) {
        service.editTest(semester, id, course);
    }

Everything works as expected when I add the JSON for the first time and I get the correct JSON structure. However, it becomes complex when adding and editing values.

  1. [SOLVED] Whenever I add a single object to an array, it replaces all the objects that were previously in the array. For instance, I have two objects in the "Spring 2020" array. If I make another POST request with addCourse(), both the objects get replaced
  2. [SOLVED] If I try to edit using postman, I get some exception
PUT: localhost:8080/edit/Spring20/
 >> "message": "Missing URI template variable 'semester' for method parameter of type String",

I tried looking into this but I didn't find any useful links or examples where people categorize and organize their JSON using Spring Boot. If there's anything that can help, please comment below.

EDIT The solutions below helped fix these errors. I hope this post helps anyone who might be going through the same issues!

Here's another post I made that uses the Map<> with MongoDB. CRUD operations on Array objects nested within an Object in MongoDB Spring Boot

3
  • 1
    /edit/{semster}/{id} expect something like edit/spring20/1 here spring20 is semster an 1 is id. And you are not taking PathVariable for semster Commented Oct 25, 2020 at 5:16
  • 1
    This is unfortunately one of the very common difficulties with REST APIs. Ideas such as JSON Patch try to solve it, but that's only occasionally used (and Spring doesn't have built-in support). Commented Oct 25, 2020 at 5:38
  • Yeah, I didn't find any online resources that dealt with this problem. I'm glad I was able to get help and find a solution! Commented Oct 25, 2020 at 17:31

1 Answer 1

1

Take a look at the following:

Whenever I add a single object to an array, it replaces all the objects that were previously in the array. For instance, I have two objects in the "Spring 2020" array. If I make another POST request with addCourse(), both the objects get replaced.

The problem is that you are using map.put(). When using this method, if the map previously contained a mapping for the key, the old value is replaced by the specified value. Hence, your old values are removed.

The solution is to get and update the existing entry.

public void add( Map<String, List<Courses>> course) {
    course.forEach((semester, list) -> {
        if(courseList.contains(semester)) {
            courseList.get(semester).addAll(list); // Note, list accepts duplicates
        } else {
            courseList.put(semester, list);
        }
    });
}

If I try to edit using postman, I get some exception. PUT: localhost:8080/edit/Spring20/ "message": "Missing URI template variable 'semester' for method parameter of type String",

The problem is that your path variable name semester does not match the name in the url semster. Hence, Missing URI template variable 'semester'

@RequestMapping(method=RequestMethod.PUT, value="/edit/{semester}/{id}")
public void addCourse(@PathVariable("semester") String semester, @PathVariable("id") String id, @RequestBody Courses course) {
    service.editTest(semester, course);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.