At it's core, this is a simple matter of array transposition (swapping the first and second level keys). You have a couple of simple preparations that need to be implementing before transposing the data though. First you'll need to decode the json strings. Also, you'll need to settle on a technique to inject your new, preferred non-numeric keys (to become the second level keys).
I'll wrap this task in an immediately invoked functional expression so that the non-numeric keys can be describes as function arguments and dynamically fed to the transposing, nested-loop structure.
Code: (Demo)
$names = '{"3":"test","4":"exam"}';
$quantities = '{"3":"12","4":"19"}';
var_export(
(function($name, $quantity) {
$result = [];
foreach (get_defined_vars() as $k => $row) {
foreach ($row as $i => $v) {
$result[$i][$k] = $v;
}
};
return ['final' => $result];
})(json_decode($names, true), json_decode($quantities, true))
);