This comment on another post sent me off in the right direction for a solution that converts the indexed array of a block template to an associative array that resembles the output of parse_blocks (below).
But the larger question still remains: why would block templates not follow the same structure and format that parse_blocks uses? Are they not meant to be used in similar ways? Is there some other native solution for converting a block template into renderable post content or even rendered html?
Here’s a stop gap solution that converts the indexed array of a block template into the associative array that serialize_blocks requires:
function block_template_to_associative_array( $blocks ){
$blocks_array = [];
foreach( $blocks as $block ):
$blocks_array[] = [
'blockName' => $block[0],
'attrs' => $block[1] ?? [],
'innerBlocks' => isset( $block[2] ) ? block_template_to_associative_array( $block[2] ) : [],
'innerHTML' => $block[3] ?? [],
'innerContent' => $block[4] ?? []
];
endforeach;
return $blocks_array;
}
Edit: unfortunately this is only a partial solution. It results in something close to what parse_blocks creates from post_content, but lacking the innerHTML and innerContent necessary to properly render in the editor. Using serialize_blocks and then inserting into post_content results in “This block contains unexpected or invalid content” errors, but attempting Block Recovery successfully restores all blocks and inner blocks.