Aubrey Huff hit two solo home runs and added an RBI single in San Francisco's 14th victory in 18 games. The Giants scored two unearned runs on consecutive throwing errors by starting pitcher Edwin Jackson. A third unearned run came home after right fielder Justin Upton misjudged a fly ball in the ninth inning.
Johnson, the third major league player to hit for the cycle this season, hit a solo home run in the first, doubled in the fifth and tripled in two runs when the Diamondbacks took a 4-3 lead in the sixth. He completed the feat with a line-drive single in the eighth, becoming the fourth Arizona player to hit for the cycle in the franchise's 13-year history.
The throwing errors by Jackson (6-9) came on what were intended to be sacrifice bunts in the Giants' three-run seventh.
Chris Ray (3-0) got one out for the win and Brian Wilson tossed 1 1-3 scoreless innings for his 28th save in 30 opportunities. The game went 3 hours, 45 minutes, with Arizona stranding 14 runners and San Francisco nine.
Huff had his third multihomer effort of the season as the Giants stayed three games behind first-place San Diego in the NL West.
San Francisco starter Jonathan Sanchez left after five with a 2-1 lead and the Giants made it 3-1 when Huff homered in the sixth.
Johnson joined Bengie Molina of the Texas Rangers and Jody Gerut of the Milwaukee Brewers as players to hit for the cycle this season.
Johnson completed the most difficult part when he tripled to left-center off Santiago Casilla with two outs in the seventh to tie it at 3. Adam LaRoche's RBI single put Arizona up 4-3.
Jackson needed little time to waste it.
Nate Schierholz singled and Eli Whiteside put down a sacrifice bunt. Jackson fielded it, but his toss to LaRoche was high and the first baseman had to jump slightly to catch it. Whiteside and LaRoche touched the base virtually at the same time and the runner was safe.