If you want to use the payload directly, you can also do it like this, note that I clear the msg payload first to make sure there are no variables other than the one you need:
// some code first?
msg.topic = "light";
msg.payload = {}; // this will clean the existing payload
msg.payload.state = "ON"; // adds the property and assigns it the value
return msg;
Using either option is a matter of personal preference. I tend to work on temporary variables, do all the operations there, and assign it to msg in the end.
It wouldn't be the first time I unadvertently modify or overwrite the payload, clearing the previous value, then try to read another value contained in it and does not work, or I get a wrong value. Working as in option 1 prevents that. But if the function is simple enough, where you only have to read a handful of values, it shouldn't be a problem.