One way is to create more constructors and another is to loose the immutability and introduce setter methods.
Hence, you can use Builder Pattern as Builder Pattern will help you to consume additional attributes while retaining the immutability of Item class.
Below is the coded solution. This uses a additional class ItemBuilder which helps us in building desired Item object with all mandatory attributes and combination of optional attributes, without loosing the immutability.
public class Item {
//All final attributes
private String name; // required
private int quantity; // required
private Integer ID; // optional
private Double pricePerUnit; // optional
private Double totalPrice; // optional
private Item(ItemBuilder builder) {
this.name = builder.name;
this.quantity = builder.quantity;
this.ID = builder.ID;
this.pricePerUnit = builder.pricePerUnit;
this.totalPrice = builder.totalPrice;
}
//All getter, and NO setter to provide immutability
public String getName() {
return name;
}
public int getQuantity() {
return quantity;
}
public Integer getID() {
return ID;
}
public Double getPricePerUnit() {
return pricePerUnit;
}
public Double getTotalPrice() {
return totalPrice;
}
@Override
public String toString() {
return "User: "+this.name+", "+this.quantity+", "+this.ID+", "+this.pricePerUnit+", "+this.totalPrice;
}
public static class ItemBuilder
{
private String name; // required
private int quantity; // required
private Integer ID; // optional
private Double pricePerUnit; // optional
private Double totalPrice; // optional
public ItemBuilder(String name, int quantity) {
this.name = name;
this.quantity = quantity;
}
public ItemBuilder ID(Integer ID) {
this.ID = ID;
return this;
}
public ItemBuilder pricePerUnit(Double pricePerUnit) {
this.pricePerUnit = pricePerUnit;
return this;
}
public ItemBuilder totalPrice(Double totalPrice) {
this.totalPrice = totalPrice;
return this;
}
//Return the finally constructed Item object
public Item build() {
Item item = new Item(this);
validateUserObject(item);
return item;
}
private void validateUserObject(Item item) {
//Do some basic validations to check
//if item object does not break any assumption of system
}
}
}
OR
You can also make use of JsonProperties.
@JsonIgnoreProperties(ignoreUnknown = true)
public record Item(
String name,
Integer quantity,
@JsonInclude(JsonInclude.Include.NON_NULL) Integer ID,
@JsonInclude(JsonInclude.Include.NON_NULL) Double pricePerUnit,
@JsonInclude(JsonInclude.Include.NON_NULL) Double totalPrice) {}
I hope this gives you clarity on how to resolve your problem.