For instance:
Considering type Person = {id: number; name:string; age: number; description?: {eyes: string } }
Considering user: Person
we call the endpoint GET host/user/1
Scenario 1: user with id = 1 doesnt exist:
- response1:
{id: null, name: null, age: null, description: {eyes: null}}
- response2:
{}
- response3:
null
- response4:
http no-data code (404, 204)
Scenario 2: user with id = 1 DOES exist without optional attribute description:
- response1:
{id: 1, name: "a name", age: 20 , description: {eyes: null}}
- response2:
{id: 1, name: "a name", age: 20 , description: {}}
- response3:
{id: 1, name: "a name", age: 20 , description: null}
In my opinion falsy values (or the 404/204 in the first scenario) would be the best for empty attributes as they are easier and cleaner to handle.
Note: I found several similiar questions in StackOverflow but none of then with nested objects