Cody Ross had three hits and drove in two runs for Florida, which has won 10 of 14 to stay in the playoff race. Ross extended his hitting streak to 11 games, the longest current streak in the NL, and was 5 for 12 in the series.
Florida moved within four games of wild card-leading Colorado, which was at San Francisco on Wednesday night.
Johnson (15-4) gave up one run and nine hits in his 23rd quality start of the season. He is tied for third in the National League in wins.
The Cardinals rallied in the ninth. Jason LaRue walked with one out and Mark DeRosa followed with a double to left. Marlins manager Fredi Gonzalez then replaced Brian Sanches with closer Leo Nunez, whose wildness got the Marlins into more trouble.
Nunez hit Ryan Ludwick and Albert Pujols to force in a run before coaxing Matt Holliday into a game-ending double play for his 22nd save in 28 opportunities.