diff --git a/src/fileFormats/Make/files b/src/fileFormats/Make/files
index 53d04f7852..fe8902fd83 100644
--- a/src/fileFormats/Make/files
+++ b/src/fileFormats/Make/files
@@ -42,6 +42,8 @@ gltf/foamGltfObject.C
gltf/foamGltfScene.C
gltf/foamGltfSceneWriter.C
+json/JSONformatter.C
+
starcd/STARCDCore.C
stl/STLCore.C
stl/STLReader.C
diff --git a/src/fileFormats/json/JSONformatter.C b/src/fileFormats/json/JSONformatter.C
new file mode 100644
index 0000000000..9b4b9b0ba0
--- /dev/null
+++ b/src/fileFormats/json/JSONformatter.C
@@ -0,0 +1,264 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | www.openfoam.com
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2023 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+\*---------------------------------------------------------------------------*/
+
+#include "JSONformatter.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+ defineTypeNameAndDebug(JSONformatter, 0);
+}
+
+// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
+
+bool Foam::JSONformatter::writeToken(const token& t)
+{
+ bool ok = true;
+ switch (t.type())
+ {
+ case token::tokenType::BOOL:
+ write(t.boolToken());
+ break;
+
+ case token::tokenType::LABEL:
+ write(t.labelToken());
+ break;
+
+ case token::tokenType::FLOAT:
+ case token::tokenType::DOUBLE:
+ write(t.scalarToken());
+ break;
+
+ case token::tokenType::WORD:
+ case token::tokenType::DIRECTIVE:
+ write(t.wordToken());
+ break;
+
+ case token::tokenType::STRING:
+ case token::tokenType::EXPRESSION:
+ case token::tokenType::VARIABLE:
+ case token::tokenType::VERBATIM:
+ case token::tokenType::CHAR_DATA:
+ write(t.stringToken());
+ break;
+
+ default:
+ DebugInfo
+ << "Problem converting token to JSON:" << nl
+ << " " << Foam::name(int(t.type()))
+ << " - treating as null" << endl;
+
+ os_ << "null";
+
+ ok = false;
+ break;
+ }
+
+ return ok;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::JSONformatter::JSONformatter(Ostream& os)
+:
+ os_(os)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+Foam::Ostream& Foam::JSONformatter::writeKeyword
+(
+ const keyType& keyword
+)
+{
+ return os_.writeQuoted(keyword);
+}
+
+
+Foam::Ostream& Foam::JSONformatter::writeDict(const dictionary& dict)
+{
+ if (dict.empty())
+ {
+ os_ << "{}";
+ return os_;
+ }
+
+ os_ << '{' << nl << incrIndent;
+
+ const auto openBrace = [](const token& t){
+ return t == token::BEGIN_LIST || t == token::BEGIN_SQR;
+ };
+ const auto closeBrace = [](const token& t){
+ return t == token::END_LIST || t == token::END_SQR;
+ };
+
+ label entryi = 0;
+ for (const entry& e : dict)
+ {
+ if (entryi)
+ {
+ os_ << ',' << nl;
+ }
+
+ const word& keyword = e.keyword();
+
+ os_ << indent;
+ writeKeyword(keyword) << " : ";
+
+ if (e.isDict())
+ {
+ writeDict(e.dict());
+
+ ++entryi;
+
+ continue;
+ }
+
+ const auto& tokens = e.stream();
+
+ if (tokens.empty()) continue; // error?
+
+ if (tokens.size() == 1)
+ {
+ writeToken(tokens[0]);
+ }
+ else
+ {
+ label offset = 0;
+ if (tokens[0].isLabel() && openBrace(tokens[1]))
+ {
+ offset = 1; // reading 'size (value0 value1 ... valueN)
+ }
+
+ const token& t = tokens[offset];
+ if (openBrace(t))
+ {
+ // Assume array-type
+ label i = 0;
+ for (label tokeni=offset; tokeni.
+
+Class
+ Foam::JSONformatter
+
+Description
+ An wrapper for Ostream that outputs content in JSON format.
+
+SourceFiles
+ JSONformatter.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef Foam_JSONformatter_H
+#define Foam_JSONformatter_H
+
+#include "Ostream.H"
+#include "dictionary.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+ Class JSONformatter Declaration
+\*---------------------------------------------------------------------------*/
+
+class JSONformatter
+{
+ // Private Data
+
+ //- Reference to the output stream
+ Ostream& os_;
+
+
+ // Private Member Functions
+
+ //- Write token to stream
+ bool writeToken(const token& t);
+
+
+public:
+
+ //- Declare type-name
+ TypeName("JSONformatter");
+
+ //- Construct from Ostream
+ explicit JSONformatter(Ostream& os);
+
+ //- Destructor
+ virtual ~JSONformatter() = default;
+
+
+ // Member Functions
+
+ // Write Functions
+
+ virtual Ostream& write(const bool val);
+ virtual Ostream& write(const int32_t val);
+ virtual Ostream& write(const int64_t val);
+ virtual Ostream& write(const float val );
+ virtual Ostream& write(const double val);
+ virtual Ostream& write(const word& str);
+ virtual Ostream& write(const std::string& str);
+ virtual Ostream& write(const char* str);
+
+ //- Write JSON keyword
+ virtual Ostream& writeKeyword(const keyType& keyword);
+
+ //- Write OpenFOAM dictionary to JSON dictionary
+ virtual Ostream& writeDict(const dictionary& dict);
+
+ //- Write JSON keyword-value pair
+ template
+ Ostream& writeEntry(const word& keyword, Type val)
+ {
+ writeKeyword(keyword) << " : " << write(val);
+ }
+};
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //