Serialize extension with empty object. Fixes #97
Use pretty printing JSON when serializing for the readability.
diff --git a/models/Extensions-issue97/test.gltf b/models/Extensions-issue97/test.gltf
new file mode 100644
index 0000000..c40af40
--- /dev/null
+++ b/models/Extensions-issue97/test.gltf
@@ -0,0 +1,66 @@
+
+{
+  "scenes" : [
+    {
+      "nodes" : [ 0 ]
+    }
+  ],
+  
+  "nodes" : [
+    {
+      "mesh" : 0
+    }
+  ],
+
+  "meshes" : [
+    {
+      "primitives" : [ {
+        "attributes" : {
+          "POSITION" : 0
+        }
+      } ]
+    }
+  ],
+
+  "buffers" : [
+    {
+      "uri" : "data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA",
+      "byteLength" : 36
+    }
+  ],
+  "bufferViews" : [
+    {
+      "buffer" : 0,
+      "byteOffset" : 0,
+      "byteLength" : 36,
+      "target" : 34962
+    }
+  ],
+  "accessors" : [
+    {
+      "bufferView" : 0,
+      "byteOffset" : 0,
+      "componentType" : 5126,
+      "count" : 3,
+      "type" : "VEC3",
+      "max" : [ 1.0, 1.0, 0.0 ],
+      "min" : [ 0.0, 0.0, 0.0 ]
+    }
+  ],
+  
+  "asset" : {
+    "version" : "2.0"
+  },
+
+  "materials" : [
+    { "name" : "WHITE",
+      "extensions": {
+        "VENDOR_material_some_ext" : { }
+      }
+    }
+  ],
+  
+  "extensionsUsed" : [
+    "VENDOR_material_some_ext"
+  ]
+}
diff --git a/tests/tester.cc b/tests/tester.cc
index ca0ced3..bb29e18 100644
--- a/tests/tester.cc
+++ b/tests/tester.cc
@@ -41,4 +41,48 @@
   REQUIRE(true == ret);
 }
 
+TEST_CASE("extension-with-empty-object", "[issue-97]") {
+
+  tinygltf::Model model;
+  tinygltf::TinyGLTF ctx;
+  std::string err;
+  std::string warn;
+
+  bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/Extensions-issue97/test.gltf");
+  if (!err.empty()) {
+    std::cerr << err << std::endl;
+  }
+  REQUIRE(true == ret);
+
+  REQUIRE(model.extensionsUsed.size() == 1);
+  REQUIRE(model.extensionsUsed[0].compare("VENDOR_material_some_ext") == 0);
+
+  REQUIRE(model.materials.size() == 1);
+  REQUIRE(model.materials[0].extensions.size() == 1);
+  REQUIRE(model.materials[0].extensions.count("VENDOR_material_some_ext") == 1);
+
+  // TODO(syoyo): create temp directory.
+  {
+    ret = ctx.WriteGltfSceneToFile(&model, "issue-97.gltf", true, true);
+    REQUIRE(true == ret);
+
+    tinygltf::Model m;
+
+    // read back serialized glTF
+    bool ret = ctx.LoadASCIIFromFile(&m, &err, &warn, "issue-97.gltf");
+    if (!err.empty()) {
+      std::cerr << err << std::endl;
+    }
+    REQUIRE(true == ret);
+
+    REQUIRE(m.extensionsUsed.size() == 1);
+    REQUIRE(m.extensionsUsed[0].compare("VENDOR_material_some_ext") == 0);
+
+    REQUIRE(m.materials.size() == 1);
+    REQUIRE(m.materials[0].extensions.size() == 1);
+    REQUIRE(m.materials[0].extensions.count("VENDOR_material_some_ext") == 1);
+  }
+    
+}
+
 
diff --git a/tiny_gltf.h b/tiny_gltf.h
index 8b43da0..b42020e 100644
--- a/tiny_gltf.h
+++ b/tiny_gltf.h
@@ -4115,7 +4115,17 @@
   for (ExtensionMap::iterator extIt = extensions.begin();
        extIt != extensions.end(); ++extIt) {
     json extension_values;
-    SerializeValue(extIt->first, extIt->second, extMap);
+
+    // Allow an empty object for extension(#97)
+    json ret;
+    if (ValueToJson(extIt->second, &ret)) {
+      extMap[extIt->first] = ret;
+    } else {
+      if (!(extIt->first.empty())) { // name should not be empty, but for sure 
+        // create empty object so that an extension name is still included in json.
+        extMap[extIt->first] = json({});
+      }
+    }
   }
   o["extensions"] = extMap;
 }
@@ -4760,7 +4770,8 @@
     SerializeValue("extras", model->extras, output);
   }
 
-  return WriteGltfFile(filename, output.dump());
+  // pretty printing with spacing 2
+  return WriteGltfFile(filename, output.dump(2));
 }
 
 }  // namespace tinygltf