diff --git a/JsonCpp.vcxproj b/JsonCpp.vcxproj
new file mode 100644
index 000000000..3c5a77a8f
--- /dev/null
+++ b/JsonCpp.vcxproj
@@ -0,0 +1,177 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {8B925520-1F2F-496F-BDF3-A49BB386846F}
+ Win32Proj
+ JsonCpp
+ 10.0.17763.0
+
+
+
+ StaticLibrary
+ true
+ Unicode
+ v141
+
+
+ StaticLibrary
+ true
+ Unicode
+ v141
+
+
+ StaticLibrary
+ false
+ true
+ Unicode
+ v141
+
+
+ StaticLibrary
+ false
+ true
+ Unicode
+ v141
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(SolutionDir)lib\$(Configuration)_$(PlatformShortName)\$(ProjectName)\
+ $(SolutionDir)build\$(Configuration)_$(PlatformShortName)\$(ProjectName)\
+
+
+ $(SolutionDir)lib\$(Configuration)_$(PlatformShortName)\$(ProjectName)\
+ $(SolutionDir)build\$(Configuration)_$(PlatformShortName)\$(ProjectName)\
+
+
+ $(SolutionDir)lib\$(Configuration)_$(PlatformShortName)\$(ProjectName)\
+ $(SolutionDir)build\$(Configuration)_$(PlatformShortName)\$(ProjectName)\
+
+
+ $(SolutionDir)lib\$(Configuration)_$(PlatformShortName)\$(ProjectName)\
+ $(SolutionDir)build\$(Configuration)_$(PlatformShortName)\$(ProjectName)\
+
+
+
+
+
+ Level3
+ Disabled
+ _ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ include
+ stdcpp17
+
+
+ Windows
+ true
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ include
+ stdcpp17
+
+
+ Windows
+ true
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;_ITERATOR_DEBUG_LEVEL=0;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ include
+ stdcpp17
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ include
+ stdcpp17
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JsonCpp.vcxproj.filters b/JsonCpp.vcxproj.filters
new file mode 100644
index 000000000..44c195ed4
--- /dev/null
+++ b/JsonCpp.vcxproj.filters
@@ -0,0 +1,62 @@
+
+
+
+
+ {efe9ea6e-e506-49b7-bd1d-f1eba404fc00}
+
+
+ {25362820-7c73-465e-ab0d-81088e935eb0}
+
+
+ {93ccfe8f-3fb1-4610-aafd-7e72557fcab4}
+
+
+
+
+ include\json
+
+
+ include\json
+
+
+ include\json
+
+
+ include\json
+
+
+ include\json
+
+
+ include\json
+
+
+ include\json
+
+
+ include\json
+
+
+ include
+
+
+ lib_json
+
+
+
+
+ lib_json
+
+
+ lib_json
+
+
+ lib_json
+
+
+
+
+ lib_json
+
+
+
\ No newline at end of file
diff --git a/include/JsonSerializer.h b/include/JsonSerializer.h
new file mode 100644
index 000000000..5db17f2e8
--- /dev/null
+++ b/include/JsonSerializer.h
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2011-2012 Promit Roy
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef JSONSERIALIZER_H
+#define JSONSERIALIZER_H
+
+#include
+#include
+#include
+
+enum class SerializerMode
+{
+ Reader,
+ Writer
+};
+
+class JsonSerializer
+{
+private:
+ //SFINAE garbage to detect whether a type has a Serialize member
+ typedef char SerializeNotFound;
+ struct SerializeFound { char x[2]; };
+ struct SerializeFoundStatic { char x[3]; };
+
+ template
+ struct SerializeTester { };
+ template
+ struct SerializeTesterStatic { };
+ template
+ static SerializeFound SerializeTest(SerializeTester*);
+ template
+ static SerializeFoundStatic SerializeTest(SerializeTesterStatic*);
+ template
+ static SerializeNotFound SerializeTest(...);
+
+ template
+ struct HasSerialize
+ {
+ static const bool value = sizeof(SerializeTest(0)) == sizeof(SerializeFound);
+ };
+
+ //Serialize using a free function defined for the type (default fallback)
+ template
+ void SerializeImpl(TValue& value,
+ typename std::enable_if::value >::type* dummy = 0)
+ {
+ //prototype for the serialize free function, so we will get a link error if it's missing
+ //this way we don't need a header with all the serialize functions for misc types (eg math)
+ void Serialize(TValue&, JsonSerializer&);
+
+ Serialize(value, *this);
+ }
+
+ //Serialize using a member function Serialize(JsonSerializer&)
+ template
+ void SerializeImpl(TValue& value, typename std::enable_if::value >::type* dummy = 0)
+ {
+ value.Serialize(*this);
+ }
+
+public:
+ JsonSerializer(bool isWriter)
+ : IsWriter(isWriter)
+ { }
+ JsonSerializer(bool isWriter, Json::Value value)
+ : IsWriter(isWriter), JsonValue(value)
+ { }
+ JsonSerializer(SerializerMode mode)
+ : IsWriter(mode == SerializerMode::Writer)
+ { }
+
+ template
+ void Serialize(TKey key, TValue& value, typename std::enable_if::value >::type* dummy = 0)
+ {
+ JsonSerializer subVal(IsWriter);
+ if(!IsWriter)
+ {
+ subVal.JsonValue = JsonValue[key];
+ if(subVal.JsonValue.isNull())
+ return;
+ }
+
+ subVal.SerializeImpl(value);
+
+ if(IsWriter)
+ JsonValue[key] = subVal.JsonValue;
+ }
+
+ //Serialize a string value
+ template
+ void Serialize(TKey key, std::string& value)
+ {
+ if(IsWriter)
+ Write(key, value);
+ else
+ Read(key, value);
+ }
+
+ //Serialize a non class type directly using JsonCpp
+ template
+ void Serialize(TKey key, TValue& value, typename std::enable_if::value >::type* dummy = 0)
+ {
+ if(IsWriter)
+ Write(key, value);
+ else
+ Read(key, value);
+ }
+
+ //Serialize an enum type to JsonCpp
+ template
+ void Serialize(TKey key, TEnum& value, typename std::enable_if::value >::type* dummy = 0)
+ {
+ int ival = (int) value;
+ if(IsWriter)
+ {
+ Write(key, ival);
+ }
+ else
+ {
+ Read(key, ival);
+ value = (TEnum) ival;
+ }
+ }
+
+ //Serialize only when writing (saving), useful for r-values
+ template
+ void WriteOnly(TKey key, TValue value, typename std::enable_if::value >::type* dummy = 0)
+ {
+ if(IsWriter)
+ Write(key, value);
+ }
+
+ //Serialize a series of items by start and end iterators
+ template
+ void WriteOnly(TKey key, TItor first, TItor last)
+ {
+ if(!IsWriter)
+ return;
+
+ JsonSerializer subVal(IsWriter);
+ int index = 0;
+ subVal.JsonValue = Json::arrayValue;
+ for(TItor it = first; it != last; ++it)
+ {
+ subVal.Serialize(index, *it);
+ ++index;
+ }
+ JsonValue[key] = subVal.JsonValue;
+ }
+
+ template
+ void ReadOnly(TKey key, TValue& value, typename std::enable_if::value >::type* dummy = 0)
+ {
+ if(!IsWriter)
+ Read(key, value);
+ }
+
+ template
+ void ReadOnly(std::vector& vec)
+ {
+ if(IsWriter)
+ return;
+ if(!JsonValue.isArray())
+ return;
+
+ vec.clear();
+ vec.reserve(vec.size() + JsonValue.size());
+ for(int i = 0; i < JsonValue.size(); ++i)
+ {
+ TValue val;
+ Serialize(i, val);
+ vec.push_back(val);
+ }
+ }
+
+ template
+ void Serialize(TKey key, std::vector& vec)
+ {
+ if(IsWriter)
+ {
+ WriteOnly(key, vec.begin(), vec.end());
+ }
+ else
+ {
+ JsonSerializer subVal(IsWriter);
+ subVal.JsonValue = JsonValue[key];
+ subVal.ReadOnly(vec);
+ }
+ }
+
+ template
+ void ReadOnly(std::deque& dq)
+ {
+ if(IsWriter)
+ return;
+ if(!JsonValue.isArray())
+ return;
+
+ dq.clear();
+ for(int i = 0; i < JsonValue.size(); ++i)
+ {
+ TValue val;
+ Serialize(i, val);
+ dq.push_back(val);
+ }
+ }
+
+ template
+ void Serialize(TKey key, std::deque& dq)
+ {
+ if(IsWriter)
+ {
+ WriteOnly(key, dq.begin(), dq.end());
+ }
+ else
+ {
+ JsonSerializer subVal(IsWriter);
+ subVal.JsonValue = JsonValue[key];
+ subVal.ReadOnly(dq);
+ }
+ }
+
+ template
+ void ReadOnly(std::map& m)
+ {
+ if(IsWriter)
+ return;
+ if(!JsonValue.isObject())
+ return;
+
+ m.clear();
+ for(auto it = JsonValue.begin(); it != JsonValue.end(); ++it)
+ {
+ JsonSerializer subVal(IsWriter);
+ subVal.JsonValue = *it;
+ std::string key = it.key().asString();
+ TValue value;
+ Serialize(key, value);
+ m[key] = value;
+ }
+ }
+
+ template
+ void WriteOnly(TKey key, std::map& m)
+ {
+ if(!IsWriter)
+ return;
+
+ JsonSerializer subVal(IsWriter);
+ for(auto it = m.begin(); it != m.end(); ++it)
+ {
+ subVal.Serialize(it->first, it->second);
+ }
+ JsonValue[key] = subVal.JsonValue;
+ }
+
+ template
+ void Serialize(TKey key, std::map& m)
+ {
+ if(IsWriter)
+ {
+ WriteOnly(key, m);
+ }
+ else
+ {
+ JsonSerializer subVal(IsWriter);
+ subVal.JsonValue = JsonValue[key];
+ subVal.ReadOnly(m);
+ }
+ }
+
+ //Append a Json::Value directly
+ template
+ void WriteOnly(TKey key, const Json::Value& value)
+ {
+ Write(key, value);
+ }
+
+ //Forward a pointer
+ template
+ void Serialize(TKey key, TValue* value, typename std::enable_if::value >::type* dummy = 0)
+ {
+ Serialize(key, *value);
+ }
+
+ template
+ void WriteOnly(TKey key, TValue* value, typename std::enable_if::value >::type* dummy = 0)
+ {
+ Serialize(key, *value);
+ }
+
+ template
+ void ReadOnly(TKey key, TValue* value, typename std::enable_if::value >::type* dummy = 0)
+ {
+ ReadOnly(key, *value);
+ }
+
+ //intellisense hack, doesn't do anything
+ template
+ void SerializeNVP(T name)
+ {
+ }
+
+ //Shorthand operator to serialize
+ template
+ void operator()(TKey key, TValue&& value)
+ {
+ Serialize(key, value);
+ }
+
+ Json::Value JsonValue;
+ bool IsWriter;
+
+private:
+ template
+ void Write(TKey key, TValue value)
+ {
+ JsonValue[key] = value;
+ }
+
+ template
+ void Write(TKey key, long value)
+ {
+ JsonValue[key] = (int) value;
+ }
+
+ template
+ void Write(TKey key, unsigned long value)
+ {
+ JsonValue[key] = (unsigned int) value;
+ }
+
+ template
+ void Write(TKey key, size_t value)
+ {
+ JsonValue[key] = (unsigned int)value;
+ }
+
+ template
+ void Read(TKey key, TValue& value, typename std::enable_if::value >::type* dummy = 0)
+ {
+ Json::Value subval = JsonValue[key];
+ if(subval.isNull())
+ return;
+ int ival = subval.asInt();
+ value = (TValue) ival;
+ }
+
+ template
+ void Read(TKey key, bool& value)
+ {
+ Json::Value subval = JsonValue[key];
+ if(subval.isNull())
+ return;
+ value = subval.asBool();
+ }
+
+ template
+ void Read(TKey key, int& value)
+ {
+ Json::Value subval = JsonValue[key];
+ if(subval.isNull())
+ return;
+ value = subval.asInt();
+ }
+
+ template
+ void Read(TKey key, long& value)
+ {
+ Json::Value subval = JsonValue[key];
+ if(subval.isNull())
+ return;
+ value = subval.asInt();
+ }
+
+ template
+ void Read(TKey key, unsigned int& value)
+ {
+ Json::Value subval = JsonValue[key];
+ if(subval.isNull())
+ return;
+ value = subval.asUInt();
+ }
+
+ template
+ void Read(TKey key, unsigned long& value)
+ {
+ Json::Value subval = JsonValue[key];
+ if(subval.isNull())
+ return;
+ value = subval.asUInt();
+ }
+
+ /*template
+ void Read(TKey key, size_t& value)
+ {
+ Json::Value subval = JsonValue[key];
+ if(subval.isNull())
+ return;
+ value = subval.asUInt();
+ }*/
+
+ template
+ void Read(TKey key, float& value)
+ {
+ Json::Value subval = JsonValue[key];
+ if(subval.isNull())
+ return;
+ value = subval.asFloat();
+ }
+
+ template
+ void Read(TKey key, double& value)
+ {
+ Json::Value subval = JsonValue[key];
+ if(subval.isNull())
+ return;
+ value = subval.asDouble();
+ }
+
+ template
+ void Read(TKey key, std::string& value)
+ {
+ Json::Value subval = JsonValue[key];
+ if(subval.isNull())
+ return;
+ value = subval.asString();
+ }
+};
+
+//"name value pair", derived from boost::serialization terminology
+#define NVP(name) #name, name
+#define SerializeNVP(name) Serialize(NVP(name))
+
+#endif