It’s easy to forget that JSON is a string format. While it is meant to carry a payload of a simple object, array, or primitive value, it is not those values; it is a string that can be deserialized into those values. So anything that is going to update the payload in that nested value will necessarily create a new string.
I don’t know the TW JSON tools well enough to offer alternate ways to do what you do here, but any tools that do exist will still have to replace the string value.
That is solvable:
<$action-setfield $tiddler="SomeTid" $field="text" $value={{{
[[SomeTid]get[text]jsonextract[]]
+[jsonset:object[sale3]]
+[jsonset[sale3],[discount],[60]]
+[jsonset[sale3],[price],[5.99]]
}}} />
AFAICT, there is no way to get the result back into a prettified format using wikitext. Even if we could parse it into a JS object, the stringify operator doesn’t seem to offer an indent parameter.
Edit:
Found it, it’s part of the format Operator
<$action-setfield $tiddler="SomeTid" $field="text" $value={{{
[[SomeTid]get[text]jsonextract[]]
+[jsonset:object[sale3]]
+[jsonset[sale3],[discount],[60]]
+[jsonset[sale3],[price],[5.99]]
+[format:json[4]]
}}} />