The fiery paceman added five wickets to the seven he snapped up in the first innings as Australia went 1-0 up in the three-test series by bowling out the hosts for 200.
Johnson's figures of 12 for 127 beat his previous best test return of 11 for 159 against South Africa in Perth in 2008.
"You never play a perfect game but it felt really good out there today," he told reporters.
The tourists, maintaining the form they showed in last month's 5-0 Ashes whitewash of England, completely outplayed the world's top-ranked test team.
"We worked exceptionally hard and when I look in my team mates' eyes at the moment they are so hungry to continue their success," said captain Michael Clarke.
Earlier, Australia declared on 290 for four after resuming on 288 for three.
Left-arm quickie Johnson then took over with the ball, looking almost unplayable at times with his raw pace and disconcerting bounce.
Petersen's dismissal marked the 250th test wicket for the 32-year-old.
Johnson's third victim came just before tea when JP Duminy was brilliantly caught at short leg by Alex Doolan for 10.
He then dismissed Ryan McLaren, caught behind for six off a vicious rising delivery, and AB de Villiers.
De Villiers top-scored in both innings for South Africa, making 91 in the first and 48 in the second before Steve Smith snaffled a reflex catch at short cover.
Last man Morne Morkel's ignominious run out for one ended the game, a reflection of the cricket produced by the home side throughout the match.
"We did not meet expectations and we deserve every bit (of abuse) that comes our way. It is one of the most disappointing four days we've had as a team," said South Africa skippe Smith.
The second test in Port Elizabeth gets underway on Thursday.