diff --git a/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONGeometryParser.h b/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONGeometryParser.h
index d4d05aa59ef6bbe20f2c91ee15cf23917d9b3b42..0a86afa45e4149d979f1717997cc52e93608db47 100644
--- a/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONGeometryParser.h
+++ b/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONGeometryParser.h
@@ -10,10 +10,13 @@
 #include "MantidGeometry/IDTypes.h"
 #include "MantidNexusGeometry/DllConfig.h"
 #include <Eigen/Geometry>
-#include <json/json.h>
 #include <memory>
 #include <vector>
 
+namespace Json {
+class Value;
+}
+
 namespace Mantid {
 
 namespace NexusGeometry {
@@ -78,7 +81,7 @@ public:
   const Eigen::Quaterniond &sourceOrientation() const noexcept {
     return m_sourceOrientation;
   }
-  size_t numberOfBanks() const noexcept { return m_jsonDetectorBanks.size(); }
+  size_t numberOfBanks() const noexcept { return m_detIDs.size(); }
   const std::vector<detid_t> &detectorIDs(const size_t index) const noexcept {
     return m_detIDs[index];
   }
@@ -149,10 +152,10 @@ private:
 
 private:
   std::string m_name;
-  Json::Value m_root;
-  Json::Value m_instrument;
-  Json::Value m_sample;
-  Json::Value m_source;
+  std::unique_ptr<Json::Value> m_root;
+  std::unique_ptr<Json::Value> m_instrument;
+  std::unique_ptr<Json::Value> m_sample;
+  std::unique_ptr<Json::Value> m_source;
   std::string m_sampleName;
   std::string m_sourceName;
   Eigen::Vector3d m_samplePosition;
@@ -160,13 +163,13 @@ private:
   Eigen::Vector3d m_sourcePosition;
   Eigen::Quaterniond m_sourceOrientation;
   // monitor information
-  std::vector<Json::Value> m_jsonMonitors;
+  std::vector<std::unique_ptr<Json::Value>> m_jsonMonitors;
   std::vector<Monitor> m_monitors;
   // chopper information
-  std::vector<Json::Value> m_jsonChoppers;
+  std::vector<std::unique_ptr<Json::Value>> m_jsonChoppers;
   std::vector<Chopper> m_choppers;
   // detector information
-  std::vector<Json::Value> m_jsonDetectorBanks;
+  std::vector<std::unique_ptr<Json::Value>> m_jsonDetectorBanks;
   std::vector<std::string> m_detectorBankNames;
   std::vector<std::vector<detid_t>> m_detIDs;
   std::vector<std::vector<double>> m_x;
diff --git a/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONInstrumentBuilder.h b/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONInstrumentBuilder.h
index fe7698aa61990c8baeddac1bded2db30eff31e87..43b3adbc08fe006eaeeaff3c2e59ffd512c461bb 100644
--- a/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONInstrumentBuilder.h
+++ b/Framework/NexusGeometry/inc/MantidNexusGeometry/JSONInstrumentBuilder.h
@@ -9,12 +9,14 @@
 
 #include "MantidGeometry/Instrument_fwd.h"
 #include "MantidNexusGeometry/DllConfig.h"
-#include "MantidNexusGeometry/JSONGeometryParser.h"
+#include <memory>
 #include <string>
 #include <vector>
 
 namespace Mantid {
 namespace NexusGeometry {
+class JSONGeometryParser;
+struct Chopper;
 /** JSONInstrumentBuilder : Builds in-memory instrument from json string
  * representing Nexus instrument geometry.
  */
@@ -29,7 +31,7 @@ public:
   Geometry::Instrument_const_uptr buildGeometry() const;
 
 private:
-  JSONGeometryParser m_parser;
+  std::unique_ptr<JSONGeometryParser> m_parser;
 };
 
 } // namespace NexusGeometry
diff --git a/Framework/NexusGeometry/src/JSONGeometryParser.cpp b/Framework/NexusGeometry/src/JSONGeometryParser.cpp
index 655279f41d96f5324ed9d8a68a311ad77a33beda..a45245e8ac6db8470a8ce25a2789bf43c7c46269 100644
--- a/Framework/NexusGeometry/src/JSONGeometryParser.cpp
+++ b/Framework/NexusGeometry/src/JSONGeometryParser.cpp
@@ -10,6 +10,9 @@
 #include "MantidNexusGeometry/NexusGeometryDefinitions.h"
 #include <boost/algorithm/string/classification.hpp>
 #include <boost/algorithm/string/split.hpp>
+#include <json/json.h>
+
+using Json::Value;
 
 namespace {
 using namespace Mantid::NexusGeometry;
@@ -296,6 +299,15 @@ std::string extractInstrumentName(const Json::Value &instrument) {
   return name;
 }
 
+std::vector<std::unique_ptr<Json::Value>>
+moveToUniquePtrVec(std::vector<Json::Value> &jsonVector) {
+  std::vector<std::unique_ptr<Json::Value>> ret;
+  for (auto &val : jsonVector)
+    ret.push_back(std::make_unique<Json::Value>(std::move(val)));
+
+  return ret;
+}
+
 } // namespace
 
 namespace Mantid {
@@ -325,8 +337,8 @@ void JSONGeometryParser::validateAndRetrieveGeometry(
   if (sample.isNull())
     throw std::invalid_argument("No sample found in json.");
 
-  m_source = get(entryChildren, NX_SOURCE);
-  if (m_source.isNull())
+  auto source = get(entryChildren, NX_SOURCE);
+  if (source.isNull())
     g_log.notice() << "No source information found in json instrument."
                    << std::endl;
 
@@ -336,25 +348,30 @@ void JSONGeometryParser::validateAndRetrieveGeometry(
 
   m_name = extractInstrumentName(instrument);
 
-  m_jsonDetectorBanks = getAllDetectors(instrument);
-  if (m_jsonDetectorBanks.empty())
+  auto jsonDetectorBanks = getAllDetectors(instrument);
+  if (jsonDetectorBanks.empty())
     throw std::invalid_argument("No detectors found in json.");
+  ;
+  m_jsonDetectorBanks = moveToUniquePtrVec(jsonDetectorBanks);
 
-  m_jsonMonitors = getAllMonitors(instrument);
+  auto jsonMonitors = getAllMonitors(instrument);
+  auto jsonChoppers = getAllChoppers(instrument);
 
-  m_jsonChoppers = getAllChoppers(instrument);
+  m_jsonMonitors = moveToUniquePtrVec(jsonMonitors);
+  m_jsonChoppers = moveToUniquePtrVec(jsonChoppers);
 
-  m_root = root;
-  m_sample = sample;
-  m_instrument = instrument;
+  m_root = std::make_unique<Json::Value>(std::move(root));
+  m_source = std::make_unique<Json::Value>(std::move(source));
+  m_sample = std::make_unique<Json::Value>(std::move(sample));
+  m_instrument = std::make_unique<Json::Value>(std::move(instrument));
 }
 
 void JSONGeometryParser::extractSampleContent() {
-  const auto &children = m_sample[CHILDREN];
+  const auto &children = (*m_sample)[CHILDREN];
   m_samplePosition = Eigen::Vector3d(0, 0, 0);
   m_sampleOrientation =
       Eigen::Quaterniond(Eigen::AngleAxisd(0, Eigen::Vector3d(1, 0, 0)));
-  m_sampleName = m_sample[NAME].asString();
+  m_sampleName = (*m_sample)[NAME].asString();
   for (const auto &child : children) {
     if (child[NAME] == TRANSFORMATIONS)
       extractTransformations(child, m_samplePosition, m_sampleOrientation);
@@ -366,9 +383,9 @@ void JSONGeometryParser::extractSourceContent() {
   m_sourcePosition = Eigen::Vector3d(0, 0, 0);
   m_sourceOrientation =
       Eigen::Quaterniond(Eigen::AngleAxisd(0, Eigen::Vector3d(1, 0, 0)));
-  if (!m_source.isNull()) {
-    m_sourceName = m_source[NAME].asCString();
-    const auto &children = m_source[CHILDREN];
+  if (!m_source->isNull()) {
+    m_sourceName = (*m_source)[NAME].asCString();
+    const auto &children = (*m_source)[CHILDREN];
     for (const auto &child : children) {
       if (child[NAME] == TRANSFORMATIONS)
         extractTransformations(child, m_sourcePosition, m_sourceOrientation);
@@ -382,7 +399,7 @@ void JSONGeometryParser::extractTransformationDataset(
     const Json::Value &transformation, double &value, Eigen::Vector3d &axis) {
   std::vector<double> values;
   extractDatasetValues(transformation, values);
-  axis = getTransformationAxis(m_root, transformation[ATTRIBUTES]);
+  axis = getTransformationAxis(*m_root, transformation[ATTRIBUTES]);
   value = values[0];
 }
 
@@ -429,7 +446,7 @@ void JSONGeometryParser::extractDetectorContent() {
     std::vector<uint32_t> windingOrder;
     bool isOffGeometry = false;
 
-    auto children = detector[CHILDREN];
+    auto children = (*detector)[CHILDREN];
 
     for (const auto &child : children) {
       if (child[NAME] == DETECTOR_IDS)
@@ -444,7 +461,7 @@ void JSONGeometryParser::extractDetectorContent() {
         extractShapeInformation(child, cylinders, faces, vertices, windingOrder,
                                 isOffGeometry);
       else if (child[NAME] == DEPENDS_ON)
-        verifyDependency(m_root, child);
+        verifyDependency(*m_root, child);
       else if (validateNXAttribute(child[ATTRIBUTES], NX_TRANSFORMATIONS)) {
         m_translations.emplace_back(Eigen::Vector3d());
         m_orientations.emplace_back(Eigen::Quaterniond());
@@ -452,7 +469,7 @@ void JSONGeometryParser::extractDetectorContent() {
                                m_orientations.back());
       }
     }
-    auto name = detector[NAME].asString();
+    auto name = (*detector)[NAME].asString();
     if (detIDs.empty())
       throw std::invalid_argument("No detector ids found in " + name + ".");
     if (x.empty())
@@ -482,14 +499,14 @@ void JSONGeometryParser::extractMonitorContent() {
     return;
 
   for (const auto &monitor : m_jsonMonitors) {
-    const auto &children = monitor[CHILDREN];
+    const auto &children = (*monitor)[CHILDREN];
 
     if (children.empty())
       throw std::invalid_argument(
           "Full monitor definition missing in json provided.");
 
     Monitor mon;
-    mon.componentName = monitor[NAME].asString();
+    mon.componentName = (*monitor)[NAME].asString();
     for (const auto &child : children) {
       const auto &val = child[VALUES];
       if (child[NAME] == NAME)
@@ -506,7 +523,7 @@ void JSONGeometryParser::extractMonitorContent() {
         extractShapeInformation(child, mon.cylinders, mon.faces, mon.vertices,
                                 mon.windingOrder, mon.isOffGeometry);
       else if (child[NAME] == DEPENDS_ON)
-        verifyDependency(m_root, child);
+        verifyDependency(*m_root, child);
     }
 
     if (validateShapeInformation(mon.isOffGeometry, mon.vertices, mon.cylinders,
@@ -526,13 +543,13 @@ void JSONGeometryParser::extractChopperContent() {
     return;
 
   for (const auto &chopper : m_jsonChoppers) {
-    const auto &children = chopper[CHILDREN];
+    const auto &children = (*chopper)[CHILDREN];
 
     if (children.empty())
       throw std::invalid_argument(
           "Full chopper definition missing in json provided.");
     Chopper chop;
-    chop.componentName = chopper[NAME].asString();
+    chop.componentName = (*chopper)[NAME].asString();
     for (const auto &child : children) {
       const auto &val = child[VALUES];
       if (child[NAME] == "name")
diff --git a/Framework/NexusGeometry/src/JSONInstrumentBuilder.cpp b/Framework/NexusGeometry/src/JSONInstrumentBuilder.cpp
index 6e7803a8a9c57e5bfe6935e44ddc53dfd21c907c..617045bb806594559c8439cc7b6c4a07266ca2b0 100644
--- a/Framework/NexusGeometry/src/JSONInstrumentBuilder.cpp
+++ b/Framework/NexusGeometry/src/JSONInstrumentBuilder.cpp
@@ -12,6 +12,7 @@
 #include "MantidNexusGeometry/JSONGeometryParser.h"
 #include "MantidNexusGeometry/NexusShapeFactory.h"
 #include "MantidNexusGeometry/TubeHelpers.h"
+#include <json/json.h>
 
 namespace {
 using namespace Mantid::Geometry;
@@ -95,29 +96,29 @@ void addMonitors(const JSONGeometryParser &parser, InstrumentBuilder &builder) {
 namespace Mantid {
 namespace NexusGeometry {
 JSONInstrumentBuilder::JSONInstrumentBuilder(const std::string &jsonGeometry)
-    : m_parser(jsonGeometry) {}
+    : m_parser(std::make_unique<JSONGeometryParser>(jsonGeometry)) {}
 
 const std::vector<Chopper> &JSONInstrumentBuilder::choppers() const {
-  return m_parser.choppers();
+  return m_parser->choppers();
 }
 
 Geometry::Instrument_const_uptr JSONInstrumentBuilder::buildGeometry() const {
-  InstrumentBuilder builder(m_parser.name());
-  for (size_t bank = 0; bank < m_parser.numberOfBanks(); ++bank) {
-    auto bankName = m_parser.detectorName(bank);
-    builder.addBank(bankName, m_parser.translation(bank),
-                    m_parser.orientation(bank));
-    auto shape = createShape(m_parser, bank);
-    auto pixelOffsets = getOffsets(m_parser, bank);
+  InstrumentBuilder builder(m_parser->name());
+  for (size_t bank = 0; bank < m_parser->numberOfBanks(); ++bank) {
+    auto bankName = m_parser->detectorName(bank);
+    builder.addBank(bankName, m_parser->translation(bank),
+                    m_parser->orientation(bank));
+    auto shape = createShape(*m_parser, bank);
+    auto pixelOffsets = getOffsets(*m_parser, bank);
     Eigen::Matrix<double, 3, Eigen::Dynamic> detectorPixels =
         Eigen::Affine3d::Identity() * pixelOffsets;
-    const auto &ids = m_parser.detectorIDs(bank);
-    if (m_parser.isOffGeometry(bank)) {
-      const auto &x = m_parser.xPixelOffsets(bank);
-      const auto &y = m_parser.yPixelOffsets(bank);
-      const auto &z = m_parser.zPixelOffsets(bank);
+    const auto &ids = m_parser->detectorIDs(bank);
+    if (m_parser->isOffGeometry(bank)) {
+      const auto &x = m_parser->xPixelOffsets(bank);
+      const auto &y = m_parser->yPixelOffsets(bank);
+      const auto &z = m_parser->zPixelOffsets(bank);
 
-      for (size_t i = 0; i < m_parser.detectorIDs(bank).size(); ++i) {
+      for (size_t i = 0; i < m_parser->detectorIDs(bank).size(); ++i) {
         builder.addDetectorToLastBank(bankName + "_" + std::to_string(i),
                                       ids[i], Eigen::Vector3d(x[i], y[i], z[i]),
                                       shape);
@@ -129,12 +130,12 @@ Geometry::Instrument_const_uptr JSONInstrumentBuilder::buildGeometry() const {
   }
 
   builder.addSample(
-      m_parser.sampleName(),
-      applyRotation(m_parser.samplePosition(), m_parser.sampleOrientation()));
+      m_parser->sampleName(),
+      applyRotation(m_parser->samplePosition(), m_parser->sampleOrientation()));
   builder.addSource(
-      m_parser.sourceName(),
-      applyRotation(m_parser.sourcePosition(), m_parser.sourceOrientation()));
-  addMonitors(m_parser, builder);
+      m_parser->sourceName(),
+      applyRotation(m_parser->sourcePosition(), m_parser->sourceOrientation()));
+  addMonitors(*m_parser, builder);
 
   return builder.createInstrument();
 }
diff --git a/Framework/NexusGeometry/test/JSONGeometryParserTest.h b/Framework/NexusGeometry/test/JSONGeometryParserTest.h
index be878a89a9ba445fe17ced99f10cac943e7e9418..9898537337870e5328af8d92ad833c3b48910926 100644
--- a/Framework/NexusGeometry/test/JSONGeometryParserTest.h
+++ b/Framework/NexusGeometry/test/JSONGeometryParserTest.h
@@ -14,11 +14,12 @@
 #include <Poco/Glob.h>
 #include <cxxtest/TestSuite.h>
 #include <exception>
+#include <json/json.h>
 #include <string>
 
 using namespace Mantid::Kernel;
-using Mantid::NexusGeometry::JSONGeometryParser;
 using Mantid::detid_t;
+using Mantid::NexusGeometry::JSONGeometryParser;
 
 class JSONGeometryParserTest : public CxxTest::TestSuite {
 public:
diff --git a/Framework/NexusGeometry/test/JSONInstrumentBuilderTest.h b/Framework/NexusGeometry/test/JSONInstrumentBuilderTest.h
index 99a2a443190715ea6be884431d18d21904180c1f..0019c8f74d3d9e710f9fc74f5211399510571694 100644
--- a/Framework/NexusGeometry/test/JSONInstrumentBuilderTest.h
+++ b/Framework/NexusGeometry/test/JSONInstrumentBuilderTest.h
@@ -8,9 +8,11 @@
 #define MANTID_NEXUSGEOMETRY_JSONINSTRUMENTBUILDERTEST_H_
 
 #include "MantidGeometry/Instrument.h"
+#include "MantidNexusGeometry/JSONGeometryParser.h"
 #include "MantidNexusGeometry/JSONInstrumentBuilder.h"
 #include "MantidTestHelpers/JSONGeometryParserTestHelper.h"
 #include <cxxtest/TestSuite.h>
+#include <json/json.h>
 
 using namespace Mantid;
 using Mantid::NexusGeometry::JSONInstrumentBuilder;