Born in Merthyr Tydfil, John progressed through the academy at Cardiff City. His professional debut for Cardiff came on 14 August 2012, in a 2–1 home defeat to Northampton Town in the first round of the Football League Cup. On 5 January 2013, he made his only other appearance of the season, a loss by the same margin at Macclesfield Town in the third round of the FA Cup. John made his league debut on 17 August 2013 in a 2–0 loss at West Ham United, Cardiff's first game in the Premier League. He signed a long-term contract until 2018 in December. He went on to make 20 appearances that season, appearing more frequently in the second half of the campaign, as the Bluebirds were relegated. Under new manager, Russell Slade, John fell down the pecking order and was subsequently loaned out to Barnsley for the remained of the season. He made nine appearances for the Tykes before returning to Cardiff at the end of the season. After only making a single appearance for Cardiff during the 2015–16 season, John signed for League One side Chesterfield on a month-loan deal in February, where he impressed in 6 appearances before being recalled by Cardiff on 14 April. Upon his return to Cardiff, John impressed new manager, Paul Trollope, during pre-season and went on to make his first league start for the club in over a year, where he put in a man of the match performance in a goalless draw against Birmingham City on the opening day of the season. Despite an impressive start to the season, John became a bit-part player under Neil Warnock and was told he could leave the club at the end of the season.
On 9 August 2018, John joined Swansea City on a three-year contract. He made his debut for Swansea on 28 August 2018 in the EFL Cup against Crystal Palace. John signed for Sunderland on a six-month loan on 31 January 2020.
International career
John was first called up to the Wales squad for the 2014 FIFA World Cupqualifiers against Macedonia and Serbia, in September 2013. He was an unused substitute in both games. The following month, he retained his place in the squad for the qualifiers against Macedonia and Belgium. On 11 October, John made his debut, playing the whole 90 minutes in the 1–0 win against Macedonia at the Cardiff City Stadium.