diff --git a/Data/Baseline/OTB/Files/ioTvcoreImageMetadataTest.txt b/Data/Baseline/OTB/Files/ioTvcoreImageMetadataTest.txt
new file mode 100644
index 0000000000000000000000000000000000000000..19f2ba1c0ba63171ba659f37b3d48ebc589fc24b
--- /dev/null
+++ b/Data/Baseline/OTB/Files/ioTvcoreImageMetadataTest.txt
@@ -0,0 +1,52 @@
+mytime : 2009-08-10T10:30:08.142149Z
+mytime : 2009-08-10T10:30:08.142149Z
+First try size: 512
+Second try size: 264
+Third try size: 264
+md2: {{"Extra.Comment": "Test Extrakeys",
+"ProductionDate": "2009-08-10T10:30:08.142149Z",
+"ProjectionWKT": "UTM projRef",
+"SensorID": "PHR",
+}Bands[{"": "B3",
+"PhysicalBias": "1",
+"PhysicalGain": "2",
+},{"": "B2",
+"PhysicalBias": "2",
+"PhysicalGain": "3",
+},{"": "B1",
+"PhysicalBias": "3",
+"PhysicalGain": "4",
+},]
+}
+md3: {{"Extra.Comment": "Test Extrakeys",
+"ProductionDate": "2009-08-10T10:30:08.142149Z",
+"ProjectionWKT": "UTM projRef",
+"SensorID": "PHR",
+}Bands[{"": "B3",
+"PhysicalBias": "1",
+"PhysicalGain": "2",
+},{"": "B2",
+"PhysicalBias": "2",
+"PhysicalGain": "3",
+},]
+}
+md3_append: {{"Extra.Comment": "Test Extrakeys",
+"ProductType": "Official",
+"ProjectionEPSG": "4326",
+"ProjectionWKT": "UTM projRef",
+"ProjectionProj": "+proj=longlat +datum=WGS84 +no_defs ",
+"RPC": "{"LineOffset": "0", "SampleOffset": "0", "LatOffset": "0", "LonOffset": "0", "HeightOffset": "0", "LineScale": "0", "SampleScale": "0", "LatScale": "0", "LonScale": "0", "HeightScale": "0", "LineNum": [ "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0", ], "LineDen": [ "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0", ], "SampleNum": [ "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0", ], "SampleDen": [ "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0",  "0", ], }",
+"ProductionDate": "2009-08-10T10:30:08.142149Z",
+"GCP": "{"Projection": "", [{"GCP_Id": "", "GCP_Info": "", "GCP_Row": "0", "GCP_Col": "0", "GCP_X": "0", "GCP_Y": "0", "GCP_Z": "0", }, ]}",
+"SensorID": "PHR",
+}Bands[{"": "B3",
+"PhysicalBias": "1",
+"PhysicalGain": "2",
+},{"": "B2",
+"PhysicalBias": "2",
+"PhysicalGain": "3",
+},{"": "B4",
+"PhysicalBias": "3",
+"PhysicalGain": "4",
+},]
+}
diff --git a/Modules/Core/Metadata/include/otbGeometryMetadata.h b/Modules/Core/Metadata/include/otbGeometryMetadata.h
index dbcc6febdd0f8c455401c5e8826ffb65683537fb..6a55cb9b78e6edfa19a1cc7e0074721507e8f25b 100644
--- a/Modules/Core/Metadata/include/otbGeometryMetadata.h
+++ b/Modules/Core/Metadata/include/otbGeometryMetadata.h
@@ -26,6 +26,7 @@
 
 #include <string>
 #include <vector>
+#include <sstream>
 
 namespace otb
 {
@@ -66,6 +67,7 @@ public:
   ~OTB_GCP();
 
   void Print(std::ostream& os) const;
+  std::string ToJSON(bool multiline=false) const;
 };
 
 namespace Projection
@@ -76,6 +78,9 @@ struct OTBMetadata_EXPORT GCPParam
   std::string GCPProjection;
 
   std::vector<OTB_GCP> GCPs;
+
+  // JSON export
+  std::string ToJSON(bool multiline=false) const;
 };
 
 /** \struct RPCParam
@@ -140,6 +145,18 @@ struct OTBMetadata_EXPORT RPCParam
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
 
+  // JSON export
+  std::string ToJSON(bool multiline=false) const;
+  inline static std::string doubleArrayToString(const double* array)
+  {
+    std::ostringstream oss;
+    oss << "[";
+    for (int loop = 0 ; loop < 20  ; loop++)
+    	oss << " \"" << array[loop] << "\", ";
+    oss << "]";
+    return oss.str();
+  };
+
 };
 
 // TODO : add SARParam to define a SAR sensor geometry
diff --git a/Modules/Core/Metadata/src/otbGeometryMetadata.cxx b/Modules/Core/Metadata/src/otbGeometryMetadata.cxx
index 08d8c80de0d4a319f8241c7a54d62a2098b9ffd5..4c8b19016da9cf324e2880e85761a6828750abdf 100644
--- a/Modules/Core/Metadata/src/otbGeometryMetadata.cxx
+++ b/Modules/Core/Metadata/src/otbGeometryMetadata.cxx
@@ -41,4 +41,74 @@ void OTB_GCP::Print(std::ostream& os) const
   os << "   GCP (X, Y, Z) = (" << this->m_GCPX << "," << this->m_GCPY << "," << this->m_GCPZ << ")" << std::endl;
 }
 
+std::string OTB_GCP::ToJSON(bool multiline) const
+{
+  std::ostringstream oss;
+  std::string sep;
+  if (multiline)
+  {
+    sep = "\n";
+  }
+  oss << "{"
+      << "\"GCP_Id\": \"" << this->m_Id << "\", " << sep
+      << "\"GCP_Info\": \"" << this->m_Info << "\", " << sep
+      << "\"GCP_Row\": \"" << this->m_GCPRow << "\", " << sep
+      << "\"GCP_Col\": \"" << this->m_GCPCol << "\", " << sep
+      << "\"GCP_X\": \"" << this->m_GCPX << "\", " << sep
+      << "\"GCP_Y\": \"" << this->m_GCPY << "\", " << sep
+      << "\"GCP_Z\": \"" << this->m_GCPZ << "\", " << sep
+      << "}";
+  return oss.str();
+}
+
+namespace Projection
+{
+std::string GCPParam::ToJSON(bool multiline) const
+{
+  std::ostringstream oss;
+  std::string sep;
+  if (multiline)
+  {
+    sep = "\n";
+  }
+  oss << "{"
+      << "\"Projection\": \"" << GCPProjection << "\", " << sep
+      << "[";
+  for (const auto& gcp : GCPs)
+    oss << gcp.ToJSON() << ", ";
+  oss << "]}";
+  return oss.str();
+}
+
+std::string RPCParam::ToJSON(bool multiline) const
+{
+  std::ostringstream oss;
+  std::string sep;
+  if (multiline)
+  {
+    sep = "\n";
+  }
+  oss << "{"
+      << "\"LineOffset\": \""   << LineOffset   << "\", " << sep
+	  << "\"SampleOffset\": \"" << SampleOffset << "\", " << sep
+	  << "\"LatOffset\": \""    << LatOffset    << "\", " << sep
+	  << "\"LonOffset\": \""    << LonOffset    << "\", " << sep
+	  << "\"HeightOffset\": \"" << HeightOffset << "\", " << sep
+
+	  << "\"LineScale\": \""   << LineScale   << "\", " << sep
+	  << "\"SampleScale\": \"" << SampleScale << "\", " << sep
+	  << "\"LatScale\": \""    << LatScale    << "\", " << sep
+	  << "\"LonScale\": \""    << LonScale    << "\", " << sep
+	  << "\"HeightScale\": \"" << HeightScale << "\", " << sep
+
+	  << "\"LineNum\": "   << doubleArrayToString(LineNum)   << ", " << sep
+	  << "\"LineDen\": "   << doubleArrayToString(LineDen)   << ", " << sep
+	  << "\"SampleNum\": " << doubleArrayToString(SampleNum) << ", " << sep
+	  << "\"SampleDen\": " << doubleArrayToString(SampleDen) << ", " << sep
+
+      << "}";
+  return oss.str();
+}
+
+} // end namespace Projection
 } // end namespace otb
diff --git a/Modules/Core/Metadata/src/otbImageMetadata.cxx b/Modules/Core/Metadata/src/otbImageMetadata.cxx
index 981ab5d9f14e52c20b8cf90217af8563a2e40106..ce03ef626fa24482f274ee5dcca2a99de570c189 100644
--- a/Modules/Core/Metadata/src/otbImageMetadata.cxx
+++ b/Modules/Core/Metadata/src/otbImageMetadata.cxx
@@ -210,35 +210,65 @@ bool ImageMetadataBase::Has(const std::string& key) const
 void ImageMetadataBase::ToKeywordlist(Keywordlist& kwl) const
 {
   kwl.clear();
-  // TODO : Geometry
-  // The key MDGeom::SensorGeometry should be exported as "<typeinfo>" where
-  // typeinfo is boost::any::type().name()
-  for (const auto& kv : StringKeys)
+  std::string cast_string;
+
+  // Converting the GeomKeys
+  for (const auto& kv : GeometryKeys)
+  {
+
+    if (kv.first == MDGeom::RPC)
     {
-    kwl.emplace(MetaData::MDStrNames[kv.first], kv.second);
+      Projection::RPCParam rpcStruct = boost::any_cast<Projection::RPCParam>(kv.second);
+      cast_string = rpcStruct.ToJSON();
     }
-  for (const auto& kv : NumericKeys)
+    else if (kv.first == MDGeom::ProjectionEPSG)
     {
+      cast_string = std::to_string(boost::any_cast<int>(kv.second));
+    }
+    else if (kv.first == MDGeom::GCP)
+    {
+      Projection::GCPParam gcpStruct = boost::any_cast<Projection::GCPParam>(kv.second);
+      cast_string = gcpStruct.ToJSON();
+    }
+    // TODO : MDGeom::SensorGeometry (should be exported as "<typeinfo>" where typeinfo is boost::any::type().name()
+    // TODO : MDGeom::SAR
+    // TODO : MDGeom::Adjustment
+    else
+    {
+      cast_string = boost::any_cast<std::string>(kv.second);
+    }
+    kwl.emplace(MetaData::MDGeomNames[kv.first], cast_string);
+
+  }
+  // Converting the StringKeys
+  for (const auto& kv : StringKeys)
+  {
+    kwl.emplace(MetaData::MDStrNames[kv.first], kv.second);
+  }
+  // Converting the NumericKeys
+  for (const auto& kv : NumericKeys)
+  {
     std::ostringstream oss;
     oss << kv.second;
     kwl.emplace(MetaData::MDNumNames[kv.first], oss.str());
-    }
+  }
+  // Converting the LUT1DKeys
   // TODO : LUT1D
-
+  // Convereting the LUT2DKeys
   // TODO : LUT2D
-
+  // Converting the TimeKeys
   for (const auto& kv : TimeKeys)
-    {
+  {
     std::ostringstream oss;
     oss << kv.second;
     kwl.emplace(MetaData::MDTimeNames[kv.first], oss.str());
-    }
-  
+  }
+  // Converting the ExtraKeys
   std::string prefix("Extra.");
   for (const auto& kv : ExtraKeys)
-    {
+  {
     kwl.emplace(prefix + kv.first, kv.second);
-    }
+  }
 }
 
 std::string ImageMetadataBase::ToJSON(bool multiline) const
@@ -286,8 +316,7 @@ ImageMetadata ImageMetadata::slice(int start, int end)
   // Copy the bands
   auto first = this->Bands.cbegin() + start;
   auto last = this->Bands.cbegin() + end + 1;
-  ImageMetadataBandsType vect(first, last);
-  imd.Bands = vect;
+  imd.Bands = ImageMetadataBandsType(first, last);
   return imd;
 }
 
diff --git a/Modules/Core/Metadata/test/otbImageMetadataTest.cxx b/Modules/Core/Metadata/test/otbImageMetadataTest.cxx
index e48064fee871b8932f5c5333c6dc8f821581c5b9..fa085e8d405d287ad177a1aba745b37454ecbd1f 100644
--- a/Modules/Core/Metadata/test/otbImageMetadataTest.cxx
+++ b/Modules/Core/Metadata/test/otbImageMetadataTest.cxx
@@ -38,8 +38,7 @@ int otbImageMetadataTest(int argc, char* argv[])
   using namespace otb;
 
   const char*   outFileName = argv[1];
-  std::ofstream outfile;
-  outfile.open(outFileName);
+  std::ofstream outfile(outFileName);
 
   MetaData::Time mytime;
   int year, month;
@@ -69,8 +68,7 @@ int otbImageMetadataTest(int argc, char* argv[])
 
   outfile << "mytime : "<< mytime << "\n";
 
-  MDNum someKey;
-  someKey = static_cast<MDNum>(3);
+  MDNum someKey = static_cast<MDNum>(3);
   if (someKey == MDNum::PhysicalGain)
     {
     outfile << "Found physical gain\n";
@@ -182,19 +180,24 @@ int otbImageMetadataTest(int argc, char* argv[])
   bmd.Add(MDNum::PhysicalBias,  3.0);
   md.Bands.push_back(bmd);
 
-  ImageMetadata md2;
-  md2 = md;
+  ImageMetadata md2 = md;
   md.Add(MDGeom::ProjectionWKT, std::string("Lambert projRef"));
   outfile << "md2: "<< md2 << "\n";
   
-  ImageMetadata md3;
-  md3 = md2.slice(0, 1);
+  ImageMetadata md3 = md2.slice(0, 1);
   outfile << "md3: "<< md3 << "\n";
 
   ImageMetadata md4;
   md4.Add(MDStr::SensorID, "PHR");
   md4.Add(MDStr::ProductType, "Official");
   md4.Add(std::string("Comment"), std::string("Test append"));
+  md4.Add(MDGeom::ProjectionEPSG, 4326);
+  md4.Add(MDGeom::ProjectionProj, std::string("+proj=longlat +datum=WGS84 +no_defs "));
+  Projection::RPCParam rpcStruct;
+  md4.Add(MDGeom::RPC, rpcStruct);
+  Projection::GCPParam gcpStruct;
+  gcpStruct.GCPs.push_back(OTB_GCP());
+  md4.Add(MDGeom::GCP, gcpStruct);
   bmd.Add(MDStr::BandName, "B4");
   md4.Bands.push_back(bmd);
   md3.append(md4);