Search code examples
jsonspringspring-boothttp-postspring-restcontroller

How do I map an nested JSON in a RestController?


I am trying to save nested JSON in a database using Spring Boot and RestController. Those JSONs look something like this:

{ 
 "name": "Car 1", 
 "plate_number": "PLATE NUMBER",
 "owner": { 
            "first_name": "First name",
            "last_name": "Last name"
          }
}

It was easy to map the normal fields (name and plate number) using the auto mapping provided by spring in the RestController:

public Car createProduct(Car car) {

}

But now, how can i map the object owner to it's own class, CarOwner?( I need to mention that i have multiple classes that uses this approach so a generalised way would be very useful )

EDIT:

My entities look like this:

@Entity
@Table(name = "cars")
public class Car extends BaseEntityWithName {

    private String name;

    private String plateNumber;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "owner_id")
    private Owner owner;

}

@Entity
@Table(name = "car_owners")
public class CarOwner extends BaseEntityWithName {

    private String firstName;
    private String lastName;

    // Constructor, setters, getters
}

And I'm trying to do something like this in the controller:

@RestController
@RequestMapping("/cars")
public class CarController {

    @Autowired
    private CarService carService;

    @RequestMapping(value = "/create", method = RequestMethod.POST)
    @ResponseBody
    public ProductModel createItem(Car car) {
        // How do I create the owner using the JSON parameters 
        // provided in the nested JSON?

        car.setOwner(owner); // Owner created above
        return carService.save(car);
    }

}

EDIT 2 My two services look like this. The structure is the same on both of them.

@Service
public class CarServiceImpl implements CarService {

    @Autowired
    private ProductManufacturerRepository productManufacturerRepository;

    @Autowired
    private CarRepository carRepository;

    @Override
    public List<Car> findAll() {
        return carRepository.findAll();
    }

    @Override
    public Car findOne(Long id) {
        return carRepository.findOne(id);
    }

    @Override
    @Transactional
    public Car save(Car car) {
        return carRepository.save(car);
    }

    @Override
    public void removeOne(Long id) {
        carRepository.delete(id);
    }
}

Solution

  • From your service layer I can see that you just need to save the owner class. Preferrably this would be in a separate Owner service but this is good enough for a start.

    @Service
    public class CarServiceImpl implements CarService {
    
        @Autowired
        private ProductManufacturerRepository productManufacturerRepository;
    
        @Autowired
        private CarRepository carRepository;
    
        @Override
        public List<Car> findAll() {
            return carRepository.findAll();
        }
    
        @Override
        public Car findOne(Long id) {
            return carRepository.findOne(id);
        }
    
        @Override
        @Transactional
        public Car save(Car car) {
            Owner person = car.getOwner();
            ownerRepository.save(person);
            return carRepository.save(car);
        }
    
        @Override
        public void removeOne(Long id) {
            carRepository.delete(id);
        }
    }