diff --git a/Documentation/release/dev/json-exporter-arrays.md b/Documentation/release/dev/json-exporter-arrays.md
new file mode 100644
index 0000000000000000000000000000000000000000..9ad252f304a8da35b277bca30a6497180b82aa34
--- /dev/null
+++ b/Documentation/release/dev/json-exporter-arrays.md
@@ -0,0 +1,3 @@
+## JSONSceneExporter: Support exporting a list of named actors and arrays selections
+
+vtkJSONSceneExporter is now able to export a list of named actors instead of extracting them from a renderer. With these named actors, you can select which arrays are to be exported for each actor. vtkJSONDataSetWriter now also support point and cell array selection. The protected methods `vtkJSONSceneExporter::WriteDataObject` and `vtkJSONSceneExporter::WriteDataSet` are now private.
diff --git a/IO/Export/vtkExporter.cxx b/IO/Export/vtkExporter.cxx
index 97c244efe64eb6b26f626f097e060e813dce041a..f45226c2b64a360f6b7ee4a8135503a2ed12692e 100644
--- a/IO/Export/vtkExporter.cxx
+++ b/IO/Export/vtkExporter.cxx
@@ -9,6 +9,7 @@ VTK_ABI_NAMESPACE_BEGIN
 vtkCxxSetObjectMacro(vtkExporter, RenderWindow, vtkRenderWindow);
 vtkCxxSetObjectMacro(vtkExporter, ActiveRenderer, vtkRenderer);
 
+//------------------------------------------------------------------------------
 // Construct with no start and end write methods or arguments.
 vtkExporter::vtkExporter()
 {
@@ -22,6 +23,7 @@ vtkExporter::vtkExporter()
   this->EndWriteArg = nullptr;
 }
 
+//------------------------------------------------------------------------------
 vtkExporter::~vtkExporter()
 {
   this->SetRenderWindow(nullptr);
@@ -37,6 +39,7 @@ vtkExporter::~vtkExporter()
   }
 }
 
+//------------------------------------------------------------------------------
 // Write data to output. Method executes subclasses WriteData() method, as
 // well as StartWrite() and EndWrite() methods.
 void vtkExporter::Write()
@@ -64,12 +67,14 @@ void vtkExporter::Write()
   }
 }
 
+//------------------------------------------------------------------------------
 // Convenient alias for Write() method.
 void vtkExporter::Update()
 {
   this->Write();
 }
 
+//------------------------------------------------------------------------------
 // Specify a function to be called before data is written.
 // Function will be called with argument provided.
 void vtkExporter::SetStartWrite(void (*f)(void*), void* arg)
@@ -87,6 +92,7 @@ void vtkExporter::SetStartWrite(void (*f)(void*), void* arg)
   }
 }
 
+//------------------------------------------------------------------------------
 // Set the arg delete method. This is used to free user memory.
 void vtkExporter::SetStartWriteArgDelete(void (*f)(void*))
 {
@@ -97,6 +103,7 @@ void vtkExporter::SetStartWriteArgDelete(void (*f)(void*))
   }
 }
 
+//------------------------------------------------------------------------------
 // Set the arg delete method. This is used to free user memory.
 void vtkExporter::SetEndWriteArgDelete(void (*f)(void*))
 {
@@ -107,6 +114,7 @@ void vtkExporter::SetEndWriteArgDelete(void (*f)(void*))
   }
 }
 
+//------------------------------------------------------------------------------
 // Specify a function to be called after data is written.
 // Function will be called with argument provided.
 void vtkExporter::SetEndWrite(void (*f)(void*), void* arg)
@@ -124,6 +132,7 @@ void vtkExporter::SetEndWrite(void (*f)(void*), void* arg)
   }
 }
 
+//------------------------------------------------------------------------------
 void vtkExporter::PrintSelf(ostream& os, vtkIndent indent)
 {
   this->Superclass::PrintSelf(os, indent);
@@ -165,6 +174,7 @@ void vtkExporter::PrintSelf(ostream& os, vtkIndent indent)
   }
 }
 
+//------------------------------------------------------------------------------
 vtkMTimeType vtkExporter::GetMTime()
 {
   vtkMTimeType mTime = this->vtkObject::GetMTime();
diff --git a/IO/Export/vtkJSONDataSetWriter.cxx b/IO/Export/vtkJSONDataSetWriter.cxx
index 81eec8fd74834afd98cc1a9fcad17f1076422a7c..0a29070dd083f47285f674d2d669b38cc4a5271a 100644
--- a/IO/Export/vtkJSONDataSetWriter.cxx
+++ b/IO/Export/vtkJSONDataSetWriter.cxx
@@ -39,6 +39,8 @@ vtkJSONDataSetWriter::vtkJSONDataSetWriter()
 {
   this->Archiver = vtkArchiver::New();
   this->ValidStringCount = 1;
+  this->GetPointArraySelection()->SetUnknownArraySetting(1);
+  this->GetCellArraySelection()->SetUnknownArraySetting(1);
 }
 
 //------------------------------------------------------------------------------
@@ -94,6 +96,23 @@ std::string vtkJSONDataSetWriter::WriteDataSetAttributes(
       continue;
     }
 
+    if (std::string(className) == "pointData")
+    {
+      if (!this->GetPointArraySelection()->ArrayIsEnabled(field->GetName()))
+      {
+        vtkDebugMacro("Skipping writing point array " << field->GetName());
+        continue;
+      }
+    }
+    else if (std::string(className) == "cellData")
+    {
+      if (!this->GetCellArraySelection()->ArrayIsEnabled(field->GetName()))
+      {
+        vtkDebugMacro("Skipping cell array " << field->GetName());
+        continue;
+      }
+    }
+
     if (nbArrayWritten)
     {
       jsonSnippet << ",\n";
@@ -384,6 +403,15 @@ bool vtkJSONDataSetWriter::WriteArrayAsRAW(vtkDataArray* array, const char* file
 void vtkJSONDataSetWriter::PrintSelf(ostream& os, vtkIndent indent)
 {
   this->Superclass::PrintSelf(os, indent);
+
+  os << indent << "Archiver:" << endl;
+  this->Archiver->PrintSelf(os, indent.GetNextIndent());
+
+  os << indent << "PointArraySelection:" << endl;
+  this->PointArraySelection->PrintSelf(os, indent.GetNextIndent());
+
+  os << indent << "CelltArraySelection:" << endl;
+  this->CellArraySelection->PrintSelf(os, indent.GetNextIndent());
 }
 
 //------------------------------------------------------------------------------
diff --git a/IO/Export/vtkJSONDataSetWriter.h b/IO/Export/vtkJSONDataSetWriter.h
index 29510cceaf9646c1485f0c243eb01de56b976d24..e3628f687210221e78ac1fdf7a34ee746a227345 100644
--- a/IO/Export/vtkJSONDataSetWriter.h
+++ b/IO/Export/vtkJSONDataSetWriter.h
@@ -32,6 +32,9 @@
 
 #include <string> // std::string used as parameters in a few methods
 
+#include "vtkDataArraySelection.h" // Instantiated
+#include "vtkNew.h"                // Used for DataArray selection
+
 VTK_ABI_NAMESPACE_BEGIN
 class vtkDataSet;
 class vtkDataArray;
@@ -118,6 +121,16 @@ public:
   vtkGetObjectMacro(Archiver, vtkArchiver);
   ///@}
 
+  /**
+   * Specify which point arrays should be written.
+   */
+  vtkGetObjectMacro(PointArraySelection, vtkDataArraySelection);
+
+  /**
+   * Specify which cell arrays should be written.
+   */
+  vtkGetObjectMacro(CellArraySelection, vtkDataArraySelection);
+
   void Write(vtkDataSet*);
 
   bool IsDataSetValid() { return this->ValidDataSet; }
@@ -139,6 +152,9 @@ protected:
 private:
   vtkJSONDataSetWriter(const vtkJSONDataSetWriter&) = delete;
   void operator=(const vtkJSONDataSetWriter&) = delete;
+
+  vtkNew<vtkDataArraySelection> PointArraySelection;
+  vtkNew<vtkDataArraySelection> CellArraySelection;
 };
 
 VTK_ABI_NAMESPACE_END
diff --git a/IO/Export/vtkJSONSceneExporter.cxx b/IO/Export/vtkJSONSceneExporter.cxx
index 476f169895c3e7cd7187e3b4d364b72c90a8344c..503d60212a06f449100abfa3b0e3e35dd22a6ae6 100644
--- a/IO/Export/vtkJSONSceneExporter.cxx
+++ b/IO/Export/vtkJSONSceneExporter.cxx
@@ -47,7 +47,6 @@ VTK_ABI_NAMESPACE_BEGIN
 vtkStandardNewMacro(vtkJSONSceneExporter);
 
 //------------------------------------------------------------------------------
-
 vtkJSONSceneExporter::vtkJSONSceneExporter()
 {
   this->FileName = nullptr;
@@ -61,7 +60,6 @@ vtkJSONSceneExporter::vtkJSONSceneExporter()
 }
 
 //------------------------------------------------------------------------------
-
 vtkJSONSceneExporter::~vtkJSONSceneExporter()
 {
   this->SetFileName(nullptr);
@@ -70,9 +68,21 @@ vtkJSONSceneExporter::~vtkJSONSceneExporter()
 }
 
 //------------------------------------------------------------------------------
+void vtkJSONSceneExporter::SetNamedActorsMap(std::map<std::string, vtkActor*>& map)
+{
+  this->NamedActorsMap = map;
+  this->Modified();
+}
+
+//------------------------------------------------------------------------------
+std::map<std::string, vtkActor*> vtkJSONSceneExporter::GetNamedActorsMap()
+{
+  return this->NamedActorsMap;
+}
 
+//------------------------------------------------------------------------------
 void vtkJSONSceneExporter::WriteDataObject(
-  ostream& os, vtkDataObject* dataObject, vtkActor* actor = nullptr, vtkVolume* volume = nullptr)
+  ostream& os, vtkDataObject* dataObject, vtkActor* actor, vtkVolume* volume, const char* name)
 {
   // Skip if nothing to process
   if (dataObject == nullptr)
@@ -107,7 +117,7 @@ void vtkJSONSceneExporter::WriteDataObject(
     }
     std::string addOnMeta = renderingSetup + texturesString + "\n";
     std::string dsMeta =
-      this->WriteDataSet(vtkDataSet::SafeDownCast(dataObject), addOnMeta.c_str());
+      this->WriteDataSet(vtkDataSet::SafeDownCast(dataObject), addOnMeta.c_str(), name);
     if (!dsMeta.empty())
     {
       os << dsMeta;
@@ -125,7 +135,7 @@ void vtkJSONSceneExporter::WriteDataObject(
     iter->InitTraversal();
     while (!iter->IsDoneWithTraversal())
     {
-      this->WriteDataObject(os, iter->GetCurrentDataObject(), actor, volume);
+      this->WriteDataObject(os, iter->GetCurrentDataObject(), actor, volume, name);
       iter->GoToNextItem();
     }
 
@@ -198,13 +208,12 @@ void vtkJSONSceneExporter::WriteDataObject(
     normalFilter->Update();
 
     // Write tubes and spheres
-    this->WriteDataObject(os, stickFilter->GetOutput(), actor, volume);
-    this->WriteDataObject(os, normalFilter->GetOutput(), actor, volume);
+    this->WriteDataObject(os, stickFilter->GetOutput(), actor, volume, name);
+    this->WriteDataObject(os, normalFilter->GetOutput(), actor, volume, name);
   }
 }
 
 //------------------------------------------------------------------------------
-
 std::string vtkJSONSceneExporter::ExtractColorTransferFunctionSetup(
   vtkColorTransferFunction* function)
 {
@@ -260,7 +269,6 @@ std::string vtkJSONSceneExporter::ExtractColorTransferFunctionSetup(
 }
 
 //------------------------------------------------------------------------------
-
 std::string vtkJSONSceneExporter::ExtractPiecewiseFunctionSetup(vtkPiecewiseFunction* function)
 {
   bool clamping = function->GetClamping();
@@ -429,12 +437,12 @@ std::string vtkJSONSceneExporter::ExtractActorRenderingSetup(vtkActor* actor)
 }
 
 //------------------------------------------------------------------------------
-
 std::string vtkJSONSceneExporter::GetTemporaryPath() const
 {
   return std::string(this->FileName) + ".pvtmp";
 }
 
+//------------------------------------------------------------------------------
 std::string vtkJSONSceneExporter::CurrentDataSetPath() const
 {
   std::stringstream path;
@@ -443,8 +451,8 @@ std::string vtkJSONSceneExporter::CurrentDataSetPath() const
 }
 
 //------------------------------------------------------------------------------
-
-std::string vtkJSONSceneExporter::WriteDataSet(vtkDataSet* dataset, const char* addOnMeta = nullptr)
+std::string vtkJSONSceneExporter::WriteDataSet(
+  vtkDataSet* dataset, const char* addOnMeta, const char* name)
 {
   if (!dataset)
   {
@@ -467,6 +475,32 @@ std::string vtkJSONSceneExporter::WriteDataSet(vtkDataSet* dataset, const char*
   vtkNew<vtkJSONDataSetWriter> dsWriter;
   dsWriter->SetInputData(dataset);
   dsWriter->GetArchiver()->SetArchiveName(dsPath.c_str());
+
+  // Parse MapPointArrays's list of arrays, filter the ones that start with "propName:X", and
+  // forward information about X to the writer
+  for (int id = 0; id < this->PointArraySelection->GetNumberOfArrays(); id++)
+  {
+    std::string currentName = this->PointArraySelection->GetArrayName(id);
+    if (currentName.find(name) != std::string::npos && currentName[std::string(name).size()] == ':')
+    {
+      std::string arrayName = currentName.substr(std::string(name).size() + 1);
+      dsWriter->GetPointArraySelection()->SetArraySetting(
+        arrayName.c_str(), this->PointArraySelection->ArrayIsEnabled(currentName.c_str()));
+    }
+  }
+
+  // Same for cell arrays
+  for (int id = 0; id < this->CellArraySelection->GetNumberOfArrays(); id++)
+  {
+    std::string currentName = this->CellArraySelection->GetArrayName(id);
+    if (currentName.find(name) != std::string::npos && currentName[std::string(name).size()] == ':')
+    {
+      std::string arrayName = currentName.substr(std::string(name).size() + 1);
+      dsWriter->GetCellArraySelection()->SetArraySetting(
+        arrayName.c_str(), this->CellArraySelection->ArrayIsEnabled(currentName.c_str()));
+    }
+  }
+
   dsWriter->Write();
 
   if (!dsWriter->IsDataSetValid())
@@ -485,8 +519,9 @@ std::string vtkJSONSceneExporter::WriteDataSet(vtkDataSet* dataset, const char*
     meta << "\n";
   }
   constexpr const char* INDENT = "    ";
+  std::string dsName = (name ? name : std::to_string(this->DatasetCount));
   meta << INDENT << "{\n"
-       << INDENT << "  \"name\": \"" << this->DatasetCount << "\",\n"
+       << INDENT << "  \"name\": \"" << dsName << "\",\n"
        << INDENT << "  \"type\": \"vtkHttpDataSetReader\",\n"
        << INDENT << "  \"vtkHttpDataSetReader\": { \"url\": \"" << this->DatasetCount << "\" }";
 
@@ -502,7 +537,6 @@ std::string vtkJSONSceneExporter::WriteDataSet(vtkDataSet* dataset, const char*
 }
 
 //------------------------------------------------------------------------------
-
 void vtkJSONSceneExporter::WriteLookupTable(const char* name, vtkScalarsToColors* lookupTable)
 {
   if (lookupTable == nullptr)
@@ -572,7 +606,7 @@ void vtkJSONSceneExporter::WritePropCollection(
       vtkMapper* mapper = actor->GetMapper();
 
       vtkDataObject* dataObject = mapper->GetInputDataObject(0, 0);
-      this->WriteDataObject(sceneComponents, dataObject, actor);
+      this->WriteDataObject(sceneComponents, dataObject, actor, nullptr, nullptr);
       this->WriteLookupTable(mapper->GetArrayName(), mapper->GetLookupTable());
     }
   }
@@ -594,7 +628,33 @@ void vtkJSONSceneExporter::WriteVolumeCollection(
 
     vtkAbstractVolumeMapper* mapper = volume->GetMapper();
     vtkDataObject* dataObject = mapper->GetInputDataObject(0, 0);
-    this->WriteDataObject(sceneComponents, dataObject, nullptr, volume);
+    this->WriteDataObject(sceneComponents, dataObject, nullptr, volume, nullptr);
+  }
+}
+
+//------------------------------------------------------------------------------
+void vtkJSONSceneExporter::WriteNamedActors(
+  std::map<std::string, vtkActor*>& actorMap, std::ostream& sceneComponents)
+{
+  for (auto it = actorMap.begin(); it != actorMap.end(); it++)
+  {
+    vtkProp* prop = vtkProp::SafeDownCast(it->second);
+    // Skip non-visible actors
+    if (!prop || !prop->GetVisibility())
+    {
+      continue;
+    }
+
+    // Skip actors with no geometry
+    vtkActor* actor = vtkActor::SafeDownCast(prop);
+    if (actor)
+    {
+      vtkMapper* mapper = actor->GetMapper();
+
+      vtkDataObject* dataObject = mapper->GetInputDataObject(0, 0);
+      this->WriteDataObject(sceneComponents, dataObject, actor, nullptr, it->first.c_str());
+      this->WriteLookupTable(mapper->GetArrayName(), mapper->GetLookupTable());
+    }
   }
 }
 
@@ -631,8 +691,16 @@ void vtkJSONSceneExporter::WriteData()
   std::stringstream sceneComponents;
   vtkPropCollection* renProps = renderer->GetViewProps();
 
-  this->WritePropCollection(renProps, sceneComponents);
-  this->WriteVolumeCollection(renderer->GetVolumes(), sceneComponents);
+  auto actorMap = this->GetNamedActorsMap();
+  if (!actorMap.empty())
+  {
+    this->WriteNamedActors(actorMap, sceneComponents);
+  }
+  else
+  {
+    this->WritePropCollection(renProps, sceneComponents);
+    this->WriteVolumeCollection(renderer->GetVolumes(), sceneComponents);
+  }
 
   std::stringstream sceneJsonFile;
   sceneJsonFile << "{\n"
@@ -685,6 +753,7 @@ void vtkJSONSceneExporter::WriteData()
   }
 }
 
+//------------------------------------------------------------------------------
 namespace
 {
 
@@ -710,7 +779,6 @@ size_t getFileSize(const std::string& path)
 } // end anon namespace
 
 //------------------------------------------------------------------------------
-
 std::string vtkJSONSceneExporter::WriteTexture(vtkTexture* texture)
 {
   // If this texture has already been written, just re-use the one
@@ -747,7 +815,6 @@ std::string vtkJSONSceneExporter::WriteTexture(vtkTexture* texture)
 }
 
 //------------------------------------------------------------------------------
-
 std::string vtkJSONSceneExporter::WriteTextureLODSeries(vtkTexture* texture)
 {
   // If this texture has already been written, just re-use the one
@@ -838,7 +905,6 @@ std::string vtkJSONSceneExporter::WriteTextureLODSeries(vtkTexture* texture)
 }
 
 //------------------------------------------------------------------------------
-
 vtkSmartPointer<vtkPolyData> vtkJSONSceneExporter::WritePolyLODSeries(
   vtkPolyData* dataset, std::string& polyLODsConfig)
 {
@@ -1034,7 +1100,6 @@ vtkSmartPointer<vtkPolyData> vtkJSONSceneExporter::WritePolyLODSeries(
 }
 
 //------------------------------------------------------------------------------
-
 void vtkJSONSceneExporter::PrintSelf(ostream& os, vtkIndent indent)
 {
   this->Superclass::PrintSelf(os, indent);
diff --git a/IO/Export/vtkJSONSceneExporter.h b/IO/Export/vtkJSONSceneExporter.h
index ef81e7e971b7b80a8b074f30b58f4493e746fd81..892300f5610a6753e91519fa9934ac2bc1f61b54 100644
--- a/IO/Export/vtkJSONSceneExporter.h
+++ b/IO/Export/vtkJSONSceneExporter.h
@@ -13,8 +13,10 @@
 #ifndef vtkJSONSceneExporter_h
 #define vtkJSONSceneExporter_h
 
+#include "vtkDataArraySelection.h" // Instantiated
 #include "vtkExporter.h"
 #include "vtkIOExportModule.h" // For export macro
+#include "vtkNew.h"            // For vtkDataArraySelection
 #include "vtkSmartPointer.h"   // For vtkSmartPointer
 
 #include <map>    // For member variables
@@ -133,6 +135,29 @@ public:
   vtkGetStringMacro(PolyLODsBaseUrl);
   ///@}
 
+  ///@{
+  /**
+   * Return the object used for point/array selection.
+   * This can only be used when using `WriteNamedActors`: an array is selected for a source by
+   * enabling the array `actorName:arrayName` in here.
+   */
+  vtkGetObjectMacro(PointArraySelection, vtkDataArraySelection);
+  vtkGetObjectMacro(CellArraySelection, vtkDataArraySelection);
+  ///@}
+
+  ///@{
+  /**
+   * Instead of using a render window that contains a scene to be written, use a map of named actors
+   * whose source datasets need to be written. This allows for point and cell array selections using
+   * PointArraySelection and CellArraySelection.
+   *
+   * If this map is specified and has non-null size, the render widows/renderer passed will be
+   * ignored, and the map used instead as the export content.
+   */
+  void SetNamedActorsMap(std::map<std::string, vtkActor*>& map);
+  std::map<std::string, vtkActor*> GetNamedActorsMap();
+  ///@}
+
 protected:
   vtkJSONSceneExporter();
   ~vtkJSONSceneExporter() override;
@@ -140,12 +165,10 @@ protected:
   void WritePropCollection(vtkPropCollection* collection, std::ostream& sceneComponents);
   void WriteVolumeCollection(vtkVolumeCollection* volumeCollection, std::ostream& sceneComponents);
 
-  void WriteDataObject(ostream& os, vtkDataObject* dataObject, vtkActor* actor, vtkVolume* volume);
   std::string ExtractPiecewiseFunctionSetup(vtkPiecewiseFunction* pwf);
   std::string ExtractColorTransferFunctionSetup(vtkColorTransferFunction* volume);
   std::string ExtractVolumeRenderingSetup(vtkVolume* volume);
   std::string ExtractActorRenderingSetup(vtkActor* actor);
-  std::string WriteDataSet(vtkDataSet* dataset, const char* addOnMeta);
   void WriteLookupTable(const char* name, vtkScalarsToColors* lookupTable);
 
   void WriteData() override;
@@ -185,6 +208,31 @@ protected:
 private:
   vtkJSONSceneExporter(const vtkJSONSceneExporter&) = delete;
   void operator=(const vtkJSONSceneExporter&) = delete;
+
+  /**
+   * Write a collection of datasets as inputs of named actors to the output stream.
+   */
+  void WriteNamedActors(std::map<std::string, vtkActor*>& actorMap, std::ostream& sceneComponents);
+
+  /**
+   * Write named dataset to file
+   */
+  std::string WriteDataSet(vtkDataSet* dataset, const char* addOnMeta, const char* name);
+
+  /**
+   * Write a dataobject to the exported file. If associated to an actor, write its texture as well
+   * as rendering setup. If associated to a volume, write its rendering setup too.
+   *
+   * The exported data object can be named, otherwise its name in the file will be the next
+   * available positive integer.
+   */
+  void WriteDataObject(
+    ostream& os, vtkDataObject* dataObject, vtkActor* actor, vtkVolume* volume, const char* name);
+
+  // Map named sources with their data array selection
+  vtkNew<vtkDataArraySelection> PointArraySelection;
+  vtkNew<vtkDataArraySelection> CellArraySelection;
+  std::map<std::string, vtkActor*> NamedActorsMap;
 };
 
 VTK_ABI_NAMESPACE_END