Skip to content

Ignore null properties in the JSON response #1047

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
hershmire opened this issue Aug 5, 2024 · 8 comments
Closed

Ignore null properties in the JSON response #1047

hershmire opened this issue Aug 5, 2024 · 8 comments
Labels
question Further information is requested

Comments

@hershmire
Copy link

You have already researched for similar issues?

I have searched around and have only found this StackOverflow question from over 2 years ago which was never answered.

What are you trying to achieve, or the steps to reproduce?

I would like to have the Fastify reply ignore sending back any properties that are null. Some of the endpoints I'm writing are for both admin and non-admin users. Admin users may have some additional properties on a resource response that I would prefer not to even make known if the response is from a non-admin. Wondering if there's any out-of-the-box way to do this.

Example Admin response:

{
  "firstName": "John",
  "lastName": "Doe",
  "signatureUrl": "https://example.com/signatures/123/signature.png"
}

Example Non-Admin response:

{
  "firstName": "John",
  "lastName": "Doe"
}

What was the result you received?

Currently I'm getting the following for the Non-Admin user since the signatureUrl field is nullable. I would like to not show this field at all to this type of user to reduce the overall payload size and not expose additional information that they are privy to.

Example Admin response:

{
  "firstName": "John",
  "lastName": "Doe",
  "signatureUrl": null
}

What did you expect?

Context

  • node version: 20
  • fastify version: >=4.28
  • os: Mac

I'm using Typescript with Typebox.

@dosubot dosubot bot added the question Further information is requested label Aug 5, 2024
@climba03003
Copy link
Member

climba03003 commented Aug 6, 2024

I would say just send what you expect.
If you don't need that property, don't send it.

You may also use preSerialization hooks to remove the null value properties, but it is expected to slow things down.

fastify.addHook('preSerialization', (_request, _reply, payload, done) => {
  // this is a loose check only, update what your needs
  if (typeof payload === 'object' && payload !== null && !Array.isArray(payload)) {
    done(null, Object.fromEntries(Object.entries(payload).filter(([_, v]) => v != null)))
  }
  done(null, payload)
})

@metcoder95
Copy link
Member

+1 on @climba03003 point.

Remember that null is a valid value as per JSON Schema spec, so it should not be stripped if you want the serializer to be spec conformant.

As said earlier, better to not send them at all.

@hershmire
Copy link
Author

If you don't need that property, don't send it.

@climba03003 @metcoder95 What do you mean? Are you referring to filtering that out prior to having it go to the serializer?

My example above is a bit trivial but I have some other use cases such as providing a default (minimal) payload and allowing consumers to add more fields when providing a search param – e.g. https://developer.x.com/en/docs/twitter-api/users/lookup/api-reference/get-users-id#tab1 user.fields.

@climba03003
Copy link
Member

What do you mean?

I means if you plan to send

{
  "firstName": "John",
  "lastName": "Doe"
}

send exactly what it is. Don't add signatureUrl.

Are you referring to filtering that out prior to having it go to the serializer?

That is one of the solution, but I don't recommend.

@hershmire
Copy link
Author

Okay... That's kind of why I created this issue in the first place. It's the same endpoint but based on the type of user who's making the request and their permissions, some fields might be filtered out at the controller layer. The intention is to not have all those fields that should be filtered show up be as null. This is not a unique question as many large APIs do this. Just curious how best to handle this within Fastify.

@jsumners
Copy link
Member

jsumners commented Aug 8, 2024

You have stumbled upon one of the most difficult authorization problems: field level authorization. We really can't help you design around this other than the recommendations provided so far. The serializer is doing what it should, serializing null to null as per spec. If you do not wish for such fields to be sent to the client, do not feed them into the serializer. Or you can provide your own serializer that is able to recognize your payloads.

@climba03003
Copy link
Member

climba03003 commented Aug 9, 2024

This is not a unique question as many large APIs do this. Just curious how best to handle this within Fastify.

Yes, it is. But most of the database support field selection, which is what similar to filter out unwanted field.
For example, MySQL can SELECT <wanted field> FROM <database>, MongoDB can project the wanted field only.
That's why I said you should send what you expected.

You can also do it in reverse way seen the optional fields is provided through query already.
In this way, you can send the expected result and prevent using value reassignment or delete.

function copy ( obj, wantedFields ) {
  const result = []
  for(const field of wantedFields) {
    result[field] = obj[field]
  }
  return result
}

The recommendation should based on what tools you choose and application design (which may not be public).
In this particular case, I would recommend you to find consultation services outside.

@climba03003
Copy link
Member

I see someone raised a PR in fast-json-stringify with your request 3 weeks ago.
So, I would close the help issue in favor of it.
Refs fastify/fast-json-stringify#731

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants