diff --git a/doc/JSON_STYLE.md b/doc/JSON_STYLE.md
index 212847eeb97c1..f6df0ccd7040d 100644
--- a/doc/JSON_STYLE.md
+++ b/doc/JSON_STYLE.md
@@ -45,3 +45,25 @@ Line breaks occur after open brackets, close brackets, or entries.
## Formatting tool
The formatting tool can be invoked via the Makefile, directly as `tools/format/json_formatter.cgi` (built via (`make json_formatter`), or via cgi at http://dev.narc.ro/cataclysm/format.html
+
+If you're using the Visual Studio solution, you can configure Visual Studio with
+commands to format all of the JSON in the project.
+
+1. Build the JsonFormatter project by either building the entire solution or
+ just that project. This will create a `tools/format/json_formatter.exe`
+ binary.
+2. Add a new external tool entry ( `Tools` > `External Tools..` > `Add` ) and
+ configure it as follows:
+ * Title: `Lint All JSON`
+ * Command: `C:\windows\system32\windowspowershell\v1.0\powershell.exe`
+ * Arguments: `-file $(SolutionDir)\style-json.ps1`
+ * Initial Directory: `$(SolutionDir)`
+ * Use Output window: *checked*
+
+At this point, you can use the menu ( `Tools` > `Lint All JSON` ) to invoke the
+command and can look in the Output Window for the output of running it.
+Additionally, you can configure a keybinding for this command by navigating to
+`Tools` > `Options` > `Environment` > `Keyboard`, searching for commands
+containing `Tools.ExternalCommand` and pick the one that corresponds to the
+position of your command in the list (e.g. `Tools.ExternalCommand1` if it's the
+top item in the list) and then assign shortcut keys to it.
\ No newline at end of file
diff --git a/msvc-full-features/Cataclysm-vcpkg-static.sln b/msvc-full-features/Cataclysm-vcpkg-static.sln
index 79de02cbe6560..ce23375f05220 100644
--- a/msvc-full-features/Cataclysm-vcpkg-static.sln
+++ b/msvc-full-features/Cataclysm-vcpkg-static.sln
@@ -15,6 +15,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cataclysm-test-vcpkg-static
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cataclysm-lib-vcpkg-static", "Cataclysm-lib-vcpkg-static.vcxproj", "{0009BB11-11AD-4C14-A5FC-D882A942C00B}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JsonFormatter", "JsonFormatter.vcxproj", "{35D74C75-FC4A-442F-AF44-43BC9D845BAF}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -47,6 +49,14 @@ Global
{0009BB11-11AD-4C14-A5FC-D882A942C00B}.Release|x64.Build.0 = Release|x64
{0009BB11-11AD-4C14-A5FC-D882A942C00B}.Release|x86.ActiveCfg = Release|Win32
{0009BB11-11AD-4C14-A5FC-D882A942C00B}.Release|x86.Build.0 = Release|Win32
+ {35D74C75-FC4A-442F-AF44-43BC9D845BAF}.Debug|x64.ActiveCfg = Debug|x64
+ {35D74C75-FC4A-442F-AF44-43BC9D845BAF}.Debug|x64.Build.0 = Debug|x64
+ {35D74C75-FC4A-442F-AF44-43BC9D845BAF}.Debug|x86.ActiveCfg = Debug|Win32
+ {35D74C75-FC4A-442F-AF44-43BC9D845BAF}.Debug|x86.Build.0 = Debug|Win32
+ {35D74C75-FC4A-442F-AF44-43BC9D845BAF}.Release|x64.ActiveCfg = Release|x64
+ {35D74C75-FC4A-442F-AF44-43BC9D845BAF}.Release|x64.Build.0 = Release|x64
+ {35D74C75-FC4A-442F-AF44-43BC9D845BAF}.Release|x86.ActiveCfg = Release|Win32
+ {35D74C75-FC4A-442F-AF44-43BC9D845BAF}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/msvc-full-features/JsonFormatter.vcxproj b/msvc-full-features/JsonFormatter.vcxproj
new file mode 100644
index 0000000000000..bf31ec6133545
--- /dev/null
+++ b/msvc-full-features/JsonFormatter.vcxproj
@@ -0,0 +1,142 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Debug
+ Win32
+
+
+ Release
+ x64
+
+
+ Release
+ Win32
+
+
+
+ 16.0
+ {35D74C75-FC4A-442F-AF44-43BC9D845BAF}
+ Win32Proj
+ JsonFormatter
+ 10.0
+ x86-windows-static
+ x64-windows-static
+
+
+
+ Application
+ v142
+ MultiByte
+
+
+ true
+
+
+ false
+ false
+
+
+
+
+
+
+
+
+
+ json_formatter
+ .exe
+ $(SolutionDir)..\tools\format\
+ $(SolutionDir)$(ProjectName)\$(Configuration)\$(Platform)\
+
+
+ true
+
+
+ false
+
+
+
+ Level1
+ Use
+ true
+ false
+ true
+ false
+ ProgramDatabase
+ 4819;4146;26495;26444;26451;4068
+ stdafx.h
+ /bigobj /utf-8 %(AdditionalOptions)
+ _SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_CONSOLE;LOCALIZE;USE_VCPKG;%(PreprocessorDefinitions)
+ stdcpp14
+ ..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ Default
+ true
+ /LTCG:OFF %(AdditionalOptions)
+ winmm.lib;imm32.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;%(AdditionalDependencies)
+
+
+ prebuild.cmd
+ Get version string
+
+
+ true
+
+
+
+
+ Disabled
+ false
+ false
+ _DEBUG;%(PreprocessorDefinitions)
+ MultiThreadedDebug
+
+
+
+
+ MaxSpeed
+ true
+ true
+ NDEBUG;%(PreprocessorDefinitions)
+ DebugFastLink
+ MultiThreaded
+
+
+ true
+ true
+
+
+
+
+ WIN32;%(PreprocessorDefinitions)
+
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+ {0009bb11-11ad-4c14-a5fc-d882a942c00b}
+
+
+
+
+
+
diff --git a/msvc-full-features/style-json.ps1 b/msvc-full-features/style-json.ps1
new file mode 100644
index 0000000000000..cd48c6c7df6ed
--- /dev/null
+++ b/msvc-full-features/style-json.ps1
@@ -0,0 +1,5 @@
+$scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
+Set-Location -Path (Join-Path -Path $scriptDir -ChildPath "..")
+$blacklist = Get-Content "json_blacklist" | Resolve-Path -Relative
+$files = Get-ChildItem -Recurse -Include *.json "data" | Resolve-Path -Relative | ?{$blacklist -notcontains $_}
+$files | ForEach-Object { Invoke-Expression ".\tools\format\json_formatter.exe $_" }
diff --git a/tools/format/format.cpp b/tools/format/format.cpp
index 05babf7761620..f661c172f8163 100644
--- a/tools/format/format.cpp
+++ b/tools/format/format.cpp
@@ -2,7 +2,11 @@
#include "getpost.h"
+#if defined(_MSC_VER)
+#include
+#else
#include
+#endif
#include
#include
#include
@@ -12,7 +16,7 @@
static void format( JsonIn &jsin, JsonOut &jsout, int depth = -1, bool force_wrap = false );
-#ifdef MSYS2
+#if defined(MSYS2) || defined(_MSC_VER)
static void erase_char( std::string &s, const char &c )
{
size_t pos = std::string::npos;
@@ -210,10 +214,15 @@ int main( int argc, char *argv[] )
std::cout << out.str();
} else {
std::string in_str = in.str();
-#ifdef MSYS2
+#if defined(MSYS2) || defined(_MSC_VER)
erase_char( in_str, '\r' );
#endif
+
+#if defined(_MSC_VER)
+ bool supports_color = _isatty( _fileno( stdout ) );
+#else
bool supports_color = isatty( STDOUT_FILENO );
+#endif
std::string color_good = supports_color ? "\x1b[32m" : std::string();
std::string color_bad = supports_color ? "\x1b[31m" : std::string();
std::string color_end = supports_color ? "\x1b[0m" : std::string();