diff --git a/Common/onelab.h b/Common/onelab.h
index 8f0c6e5f3db51b805f14bc03a3b248246bbe9bf1..6ae9071ef09ed4f49f2bdeaea0332fa75d73e46f 100644
--- a/Common/onelab.h
+++ b/Common/onelab.h
@@ -347,11 +347,63 @@ namespace onelab{
           it != getClients().end(); it++){
         if(it != getClients().begin()) sstream << ", ";
         sstream << "\"" << sanitize(it->first) << "\":"
-                << (it->second ? "true" : "false");
+                << it->second;
       }
       sstream << " }";
       return sstream.str();
     }
+    virtual bool fromJSON(const picojson::value::object& par)
+    {
+      for(picojson::value::object::const_iterator it = par.begin(); it != par.end(); ++it){
+        if(it->first == "version"){
+          if(!it->second.is<std::string>()) return false;
+          if(it->second.get<std::string>() != version()) return false;
+        }
+        else if(it->first == "name"){
+          if(!it->second.is<std::string>()) return false;
+          setName(it->second.get<std::string>());
+        }
+        else if(it->first == "label"){
+          if(!it->second.is<std::string>()) return false;
+          setLabel(it->second.get<std::string>());
+        }
+        else if(it->first == "help"){
+          if(!it->second.is<std::string>()) return false;
+          setHelp(it->second.get<std::string>());
+        }
+        else if(it->first == "changedValue"){
+          if(!it->second.is<double>()) return false;
+          setChangedValue((int)it->second.get<double>());
+        }
+        else if(it->first == "visible"){
+          if(!it->second.is<bool>()) return false;
+          setVisible(it->second.get<bool>());
+        }
+        else if(it->first == "readOnly"){
+          if(!it->second.is<bool>()) return false;
+          setReadOnly(it->second.get<bool>());
+        }
+        else if(it->first == "attributes"){
+          if(!it->second.is<picojson::object>()) return false;
+          const picojson::value::object &obj = it->second.get<picojson::object>();
+          for (picojson::value::object::const_iterator i = obj.begin(); i != obj.end(); ++i) {
+            std::string key(i->first);
+            if(!i->second.is<std::string>()) return false;
+            setAttribute(key, i->second.get<std::string>());
+          }
+        }
+        else if(it->first == "clients"){
+          if(!it->second.is<picojson::object>()) return false;
+          const picojson::value::object &obj = it->second.get<picojson::object>();
+          for (picojson::value::object::const_iterator i = obj.begin(); i != obj.end(); ++i) {
+            std::string client(i->first);
+            if(!i->second.is<double>()) return false;
+            addClient(client, (int)i->second.get<double>());
+          }
+        }
+      }
+      return true;
+    }
   };
 
   class parameterLessThan{
@@ -516,6 +568,55 @@ namespace onelab{
       sstream << " } }";
       return sstream.str();
     }
+    bool fromJSON(const picojson::value::object& par)
+    {
+      if(!parameter::fromJSON(par)) return false;
+      for(picojson::value::object::const_iterator it = par.begin(); it != par.end(); ++it){
+        if(it->first == "values"){
+          if(!it->second.is<picojson::array>()) return false;
+          const picojson::value::array &arr = it->second.get<picojson::array>();
+          _values.resize(arr.size());
+          for(unsigned int i = 0; i < arr.size(); i++){
+            if(!arr[i].is<double>()) return false;
+            _values[i] = arr[i].get<double>();
+          }
+        }
+        else if(it->first == "min"){
+          if(!it->second.is<double>()) return false;
+          setMin(it->second.get<double>());
+        }
+        else if(it->first == "max"){
+          if(!it->second.is<double>()) return false;
+          setMax(it->second.get<double>());
+        }
+        else if(it->first == "step"){
+          if(!it->second.is<double>()) return false;
+          setStep(it->second.get<double>());
+        }
+        else if(it->first == "index"){
+          if(!it->second.is<double>()) return false;
+          setIndex((int)it->second.get<double>());
+        }
+        else if(it->first == "choices"){
+          if(!it->second.is<picojson::array>()) return false;
+          const picojson::value::array &arr = it->second.get<picojson::array>();
+          _choices.resize(arr.size());
+          for(unsigned int i = 0; i < arr.size(); i++){
+            if(!arr[i].is<double>()) return false;
+            _choices[i] = arr[i].get<double>();
+          }
+        }
+        else if(it->first == "valueLabels"){
+          if(!it->second.is<picojson::object>()) return false;
+          const picojson::value::object &obj = it->second.get<picojson::object>();
+          for (picojson::value::object::const_iterator i = obj.begin(); i != obj.end(); ++i) {
+            if(!i->second.is<double>()) return false;
+            _valueLabels[i->second.get<double>()] = i->first;
+          }
+        }
+      }
+      return true;
+    }
   };
 
   // The string class. A string has a mutable "kind", that can be changed at
@@ -611,6 +712,35 @@ namespace onelab{
       sstream << " ] }";
       return sstream.str();
     }
+    bool fromJSON(const picojson::value::object& par)
+    {
+      if(!parameter::fromJSON(par)) return false;
+      for(picojson::value::object::const_iterator it = par.begin(); it != par.end(); ++it){
+        if(it->first == "values"){
+          if(!it->second.is<picojson::array>()) return false;
+          const picojson::value::array &arr = it->second.get<picojson::array>();
+          _values.resize(arr.size());
+          for(unsigned int i = 0; i < arr.size(); i++){
+            if(!arr[i].is<std::string>()) return false;
+            _values[i] = arr[i].get<std::string>();
+          }
+        }
+        else if(it->first == "kind"){
+          if(!it->second.is<std::string>()) return false;
+          setKind(it->second.get<std::string>());
+        }
+        else if(it->first == "choices"){
+          if(!it->second.is<picojson::array>()) return false;
+          const picojson::value::array &arr = it->second.get<picojson::array>();
+          _choices.resize(arr.size());
+          for(unsigned int i = 0; i < arr.size(); i++){
+            if(!arr[i].is<std::string>()) return false;
+            _choices[i] = arr[i].get<std::string>();
+          }
+        }
+      }
+      return true;
+    }
   };
 
   // The parameter space, i.e., the set of parameters stored and handled by the
@@ -842,7 +972,7 @@ namespace onelab{
       }
       return true;
     }
-    void toJSON(std::string &json, const std::string &creator="",
+    bool toJSON(std::string &json, const std::string &creator="",
                 const std::string &client="") const
     {
       time_t now;
@@ -866,6 +996,40 @@ namespace onelab{
 	}
       }
       json += "] }\n}\n";
+      return true;
+    }
+    bool fromJSON(const std::string &json, const std::string &client="")
+    {
+      picojson::value v;
+      std::string err = picojson::parse(v, json);
+      if(err.size()) return false;
+      if(!v.is<picojson::object>()) return false;
+      const picojson::value::object &obj = v.get<picojson::object>();
+      for (picojson::value::object::const_iterator i = obj.begin(); i != obj.end(); ++i) {
+        if(i->first == "onelab"){ // onelab database
+          if(!i->second.is<picojson::object>()) return false;
+          const picojson::value::object &db = i->second.get<picojson::object>();
+          for (picojson::value::object::const_iterator j = db.begin(); j != db.end(); ++j) {
+            if(j->first == "parameters"){
+              if(!j->second.is<picojson::array>()) return false;
+              const picojson::value::array &arr = j->second.get<picojson::array>();
+              for(unsigned int k = 0; k < arr.size(); k++){
+                if(!arr[k].is<picojson::object>()) return false;
+                const picojson::value::object &par = arr[k].get<picojson::object>();
+                picojson::value::object::const_iterator it = par.find("type");
+                if(it == par.end()) return false;
+                if(it->second.to_str() == "number"){
+                  number p; p.fromJSON(par); set(p, client);
+                }
+                else if(it->second.to_str() == "string"){
+                  string p; p.fromJSON(par); set(p, client);
+                }
+              }
+            }
+          }
+        }
+      }
+      return true;
     }
   };
 
@@ -1027,33 +1191,14 @@ namespace onelab{
       if(parameter::fromFile(msg, fp)) return fromChar(msg, client);
       return false;
     }
-    void toJSON(std::string &json, const std::string &client="")
+    bool toJSON(std::string &json, const std::string &client="")
     {
-      _parameterSpace.toJSON(json, client);
+      return _parameterSpace.toJSON(json, client);
     }
-    void fromJSON(const std::string &json, const std::string &client="")
+    bool fromJSON(const std::string &json, const std::string &client="")
     {
-      picojson::value v;
-      std::string err = picojson::parse(v, json);
-      if(err.size()){
-        printf("%s\n", err.c_str());
-        return;
-      }
-      // check if the type of the value is "object"
-      if(v.is<picojson::object>()) {
-        const picojson::value::object& obj = v.get<picojson::object>();
-        for (picojson::value::object::const_iterator i = obj.begin(); i != obj.end(); ++i) {
-          printf("json object %s -> %s\n", i->first.c_str(), i->second.to_str().c_str());
-          if(i->second.is<picojson::array>()){
-            const picojson::value::array& arr = i->second.get<picojson::array>();
-            for(unsigned int j = 0; j < arr.size(); j++){
-              printf(" ele %d = %s\n", j, arr[j].to_str().c_str());
-            }
-          }
-        }
-      }
+      return _parameterSpace.fromJSON(json, client);
     }
-
   };
 
   // A local client, which lives in the same memory space as the server.
diff --git a/Fltk/onelabGroup.cpp b/Fltk/onelabGroup.cpp
index 729efe7d5d168e26f40779326050edc8666fcea9..d0c25bcbf1da6fe635395092ca7fa15032474164 100644
--- a/Fltk/onelabGroup.cpp
+++ b/Fltk/onelabGroup.cpp
@@ -10,6 +10,8 @@
 #elif defined(HAVE_NO_INTPTR_T)
 typedef unsigned long intptr_t;
 #endif
+#include <fstream>
+#include <streambuf>
 #include <ctype.h>
 #include "GmshMessage.h"
 #include "onelab.h"
@@ -1205,8 +1207,11 @@ void onelabGroup::rebuildTree(bool deleteWidgets)
       free(delStrings[i]);
   }
 
-  // FIXME test
-  //onelab::server::instance()->fromJSON("{ \"key\" : [ \"hello\" , \"hello2\" ] }");
+#if 0 // test
+  std::ifstream t("test.db.json");
+  std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
+  onelab::server::instance()->fromJSON(str);
+#endif
 }
 
 void onelabGroup::openTreeItem(const std::string &name)