diff --git a/Common/gmshLocalNetworkClient.cpp b/Common/gmshLocalNetworkClient.cpp
index 8e7ec52ab5b6bfcaa8d441fe4029ef3bcb1d82db..d79e2e55d45c3877a5596c23d0360c3221867a91 100644
--- a/Common/gmshLocalNetworkClient.cpp
+++ b/Common/gmshLocalNetworkClient.cpp
@@ -624,6 +624,15 @@ void saveDb(const std::string &fileName)
   }
   else
     Msg::Error("Could not save database '%s'", fileName.c_str());
+
+  // test
+  fp = Fopen((fileName + ".json").c_str(), "wb");
+  if(fp){
+    std::string json;
+    onelab::server::instance()->toJSON(json);
+    fwrite(json.c_str(), sizeof(char), json.size(), fp);
+    fclose(fp);
+  }
 }
 
 void archiveOutputFiles(const std::string &fileName)
diff --git a/Common/onelab.h b/Common/onelab.h
index 912f0d2ddb67a6a91e4298b6b907d4b7b7e71936..678b887aab5f4fd339280d853d0099f3fd23e74b 100644
--- a/Common/onelab.h
+++ b/Common/onelab.h
@@ -267,8 +267,7 @@ namespace onelab{
       type = getNextToken(msg, first);
       name = getNextToken(msg, first);
     }
-    static bool fromFile(std::vector<std::string> &msg,
-                         FILE *fp)
+    static bool fromFile(std::vector<std::string> &msg, FILE *fp)
     {
       msg.clear();
       char tmp[1000];
@@ -284,8 +283,7 @@ namespace onelab{
       }
       return true;
     }
-    static bool toFile(const std::vector<std::string> &msg,
-                       FILE *fp,
+    static bool toFile(const std::vector<std::string> &msg, FILE *fp,
                        const std::string &creator)
     {
       time_t now;
@@ -300,6 +298,36 @@ namespace onelab{
       }
       return true;
     }
+    virtual std::string toJSON() const
+    {
+      std::ostringstream sstream;
+      sstream
+        << "\"type\":\"" << getType() << "\""
+        << ", \"version\":\"" << version() << "\""
+        << ", \"name\":\"" << sanitize(getName()) << "\""
+        << ", \"label\":\"" << sanitize(getLabel()) << "\""
+        << ", \"help\":\"" << sanitize(getHelp()) << "\""
+        << ", \"neverChanged\":" << (getNeverChanged() ? "true" : "false") << "\""
+        << ", \"visible\":" << (getVisible() ? "true" : "false") << "\""
+        << ", \"readOnly\":" << (getReadOnly() ? "true" : "false") << "\"";
+      sstream << ", \"attributes\":{ ";
+      for(std::map<std::string, std::string>::const_iterator it = _attributes.begin();
+          it != _attributes.end(); it++){
+        if(it != _attributes.begin()) sstream << ", ";
+        sstream << "\"" << sanitize(it->first) << "\":\""
+                << sanitize(it->second) << "\"";
+      }
+      sstream << " }";
+      sstream << ", \"clients\":{ ";
+      for(std::map<std::string, bool>::const_iterator it = getClients().begin();
+          it != getClients().end(); it++){
+        if(it != getClients().begin()) sstream << ", ";
+        sstream << "\"" << sanitize(it->first) << "\":"
+                << (it->second ? "true" : "false");
+      }
+      sstream << " }";
+      return sstream.str();
+    }
   };
 
   class parameterLessThan{
@@ -420,6 +448,32 @@ namespace onelab{
       }
       return pos;
     }
+    std::string toJSON() const
+    {
+      std::ostringstream sstream;
+      sstream.precision(16);
+      sstream
+        << "{ " << parameter::toJSON()
+        << ", \"value\":" << _value
+        << ", \"min\":" << _min
+        << ", \"max\":" << _max
+        << ", \"step\":" << _step
+        << ", \"index\":" << _index
+        << ", \"choices\":[ ";
+      for(unsigned int i = 0; i < _choices.size(); i++){
+        if(i) sstream << ", ";
+        sstream << _choices[i];
+      }
+      sstream << " ]";
+      sstream << ", \"valueLabels\":{ ";
+      for(std::map<double, std::string>::const_iterator it = _valueLabels.begin();
+          it != _valueLabels.end(); it++){
+        if(it != _valueLabels.begin()) sstream << ", ";
+        sstream << "\"" << sanitize(it->second) << "\":" << it->first;
+      }
+      sstream << " } }";
+      return sstream.str();
+    }
   };
 
   // The string class. A string has a mutable "kind": we do not derive
@@ -484,6 +538,21 @@ namespace onelab{
         _choices[i] = getNextToken(msg, pos);
       return pos;
     }
+    std::string toJSON() const
+    {
+      std::ostringstream sstream;
+      sstream
+        << "{ " << parameter::toJSON()
+        << ", \"value\":\"" << sanitize(_value) << "\""
+        << ", \"kind\":\"" << sanitize(_kind) <<  "\""
+        << ", \"choices\":[ ";
+      for(unsigned int i = 0; i < _choices.size(); i++){
+        if(i) sstream << ", ";
+        sstream << "\"" << sanitize(_choices[i]) << "\"";
+      }
+      sstream << " ] }";
+      return sstream.str();
+    }
   };
 
   // The parameter space, i.e., the set of parameters stored and handled by the
@@ -695,6 +764,29 @@ namespace onelab{
       }
       return true;
     }
+    void toJSON(std::string &json, const std::string &creator="",
+                const std::string &client="") const
+    {
+      time_t now;
+      time(&now);
+      std::string t(ctime(&now));
+      t.pop_back();
+      json.clear();
+      json += "{ \"onelab\":{\n";
+      json += "  \"creator\":\"" + creator + "\",\n";
+      json += "  \"date\":\"" + t + "\",\n";
+      json += "  \"parameters\":[ \n";
+      std::set<parameter*, parameterLessThan> ps;
+      _getAllParameters(ps);
+      for(std::set<parameter*, parameterLessThan>::const_iterator it = ps.begin();
+          it != ps.end(); it++){
+        if(client.empty() || (*it)->hasClient(client)){
+	  if((*it)->getAttribute("NotInDb") != "True")
+	    json += "    " + (*it)->toJSON() + "\n";
+	}
+      }
+      json += "] }\n";
+    }
   };
 
   // The onelab client: a class that communicates with the onelab server. Each
@@ -846,6 +938,10 @@ namespace onelab{
       if(parameter::fromFile(msg, fp)) return fromChar(msg, client);
       return false;
     }
+    void toJSON(std::string &json, const std::string &client="")
+    {
+      _parameterSpace.toJSON(json, client);
+    }
   };
 
   // A local client, which lives in the same memory space as the server.
@@ -945,8 +1041,7 @@ namespace onelab{
       _gmshClient->SendMessage(GmshSocket::GMSH_PARAMETER, msg.size(), &msg[0]);
       return true;
     }
-    template <class T> bool _get(std::vector<T> &ps,
-                                 const std::string &name="")
+    template <class T> bool _get(std::vector<T> &ps, const std::string &name="")
     {
       ps.clear();
       if(!_gmshClient) return false;