Jeremy Hermida's first career game-winning homer ended what had started as a matchup between aces.
Hermida hit a 1-1 pitch from reliever Jason Motte (2-2) into the right-field seats. It came after Matt Lindstrom (2-1) pitched a scoreless ninth for the Marlins, who rallied from an early three-run hole.
"He hung a slider a little bit and I was able to get the barrel on it and keep it fair," Hermida said. "All I was thinking was, 'Ballgame."'
"It wasn't a matter of me wishing I had the pitch back when I threw it," Motte said. "It just didn't have the outcome I wanted."
Carpenter allowed three runs in six innings after having given up three runs in his first six starts combined. His ERA rose from 0.79 to 1.23.
"I didn't throw well enough to win. I throw those same pitches another night and it might be a different outcome. You just never know out there," Carpenter said.
Johnson has not given up more than three earned runs in any of his last 10 starts.
"I think the win belongs to J.J. still, so I wish we could just take it off my record and give it to him," Lindstrom said.
Johnson ran into trouble in the third when Brendan Ryan and Skip Schumaker led off with singles, and Ryan raced to third when left fielder Chris Coghlan misplayed Schumaker's hit. Chris Duncan followed with an RBI single.
The Cardinals added two more runs when Rick Ankiel doubled off the wall in right, but he was thrown out trying to stretch the hit into a triple.
Emilio Bonifacio cut the lead to 3-2 with his double in the third, and he drove in his career-high third run on a single in the fifth that tied the game.
Cody Ross led off with a softly lined single to left. He moved to second on Johnson's sacrifice and took third on Coghlan's groundout. Bonifacio then hit a sharp high bouncer to the box that Carpenter got his glove on but couldn't field.
"We just came up short. The hits that they got for runs were tough to take," Cardinals manager Tony La Russa said.
Marlins catcher John Baker needed six stitches after leaving the game in the sixth with a laceration over his left eye. He was hit in the head on a swing by leadoff hitter Albert Pujols, who fouled off a pitch.