As M. Deinum correctly pointed out in the comments, the root cause is a property name mismatch between your frontend JSON and the backend Java class. Angular sends this (property name = address):
{
"customer": { ... },
"address": {
"street": "123 Main St",
"city": "Springfield",
...
},
"order": { ... },
"orderItems": \[ ... \]
}
But the Java Purchase class has:
private Address shippingAddress; // ← Jackson looks for "shippingAddress"
Jackson (Spring's JSON deserializer) matches JSON property names to Java field names (or getter/setter names). Since there is no field/property called address, that part is ignored → shippingAddress remains null. Recommended Fix : Keep your Java field name as shippingAddress, but tell Jackson to map the incoming "address" to it:
@Data
public class Purchase {
private Customer customer;
@JsonProperty("address") // ← this fixes it
private Address shippingAddress;
private Order order;
private Set<OrderItem> orderItems;
}
Just add the @JsonProperty("address") annotation (from com.fasterxml.jackson.annotation.JsonProperty).
This is the cleanest solution because:
Your domain model stays meaningful (shippingAddress)
You don't have to change the frontend
The API contract is explicitly defined
Alternative Fixes If you prefer not to use @JsonProperty, you have two other options:
export class Purchase
{
customer!: Customer;
shippingAddress!: Address; // ← now matches
order!: Order;
orderItems!: OrderItem[];
}
private Address address; // simple name
Then update any other places that reference shippingAddress.