The defeat for the hosts means they probably still need a win to book a top-six place although they stay fourth.
Town started brightly, with Dean Bowditch having a shot blocked in the opening seconds, Matthew Richards firing wide and John McGreal having a header cleared off the line by Alan Rogers.
Against the run of play, Forest went ahead on 11 minutes, Johnson shooting home after Marlon King crossed from the byline.
Paul Gerrard saved two thumping Jermaine Wright drives, while Kelvin Davis saved from Andy Reid, then dived at Johnson's feet after he raced clear.
Johnson saw a tap-in chalked off for offside after Davis beat out a Gareth Williams shot, before Town levelled on 34 minutes, Bowditch curling a 20-yard shot into the corner.
Gerrard denied Darren Bent twice, and the striker then blazed a great chance over as Town ended the half on top.
Forest went ahead again on 55 minutes when Johnson outjumped Drissa Diallo to bullet home a header from an Eoin Jess cross.
Bent shot over as Town rallied before substitutes Richard Naylor and Martijn Reuser combined, Naylor crossing perfectly for Reuser to wastefully fire over.
Bent intercepted a weak Andy Impey backpass and found Reuser, whose cross was tamely headed wide by Naylor.
King headed a Johnson cross over in a rare Forest break, before Town came desperately close to an 81st minute equaliser, Naylor thumping a header against the post from a Fabian Wilnis cross.
Town had a late penalty appeal rejected after claims of a handball as Forest's defensive wall blocked a Reuser free-kick, while Johnson could have sealed his hat-trick at the death only for Matt Elliott to block his shot.