[llvm] [Support] ScopedPrinter: support pretty-printing JSON (PR #214806)

Dan McGregor via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 7 10:55:50 PDT 2026


https://github.com/dankm created https://github.com/llvm/llvm-project/pull/214806

Add a specific printObject implementation for JSON values. For the default ScopedPrinter this supports printing with the existing indentation level. For JSONScopedPrinter it prints a raw attribute with no special handling.

I intend to use this for forthcoming support for FDO packakaging metadata support in readobj.

This is split from #214375 at the request of @jh7370.

>From f63d07db90fb6c17129200fa33d9fb4d03c5dc5c Mon Sep 17 00:00:00 2001
From: Dan McGregor <danmcgr at protonmail.com>
Date: Fri, 17 Jul 2026 13:40:40 -0600
Subject: [PATCH] [Support] ScopedPrinter: support pretty-printing JSON

Add a specific printObject implementation for JSON values.
For the default ScopedPrinter this supports printing with the
existing indentation level. For JSONScopedPrinter it prints a
raw attribute with no special handling.

I intend to use this for forthcoming support for FDO packakaging
metadata support in readobj.
---
 llvm/include/llvm/Support/JSON.h             |  7 +++--
 llvm/include/llvm/Support/ScopedPrinter.h    | 13 ++++++++
 llvm/unittests/Support/ScopedPrinterTest.cpp | 32 ++++++++++++++++++++
 3 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/Support/JSON.h b/llvm/include/llvm/Support/JSON.h
index 3b145a69c74cb..a0118ca883ce6 100644
--- a/llvm/include/llvm/Support/JSON.h
+++ b/llvm/include/llvm/Support/JSON.h
@@ -984,8 +984,9 @@ class OStream {
  public:
   using Block = llvm::function_ref<void()>;
   // If IndentSize is nonzero, output is pretty-printed.
-  explicit OStream(llvm::raw_ostream &OS, unsigned IndentSize = 0)
-      : OS(OS), IndentSize(IndentSize) {
+  explicit OStream(llvm::raw_ostream &OS, unsigned IndentSize = 0,
+                   unsigned IndentLevel = 0)
+      : OS(OS), IndentSize(IndentSize), Indent(IndentSize * IndentLevel) {
     Stack.emplace_back();
   }
   ~OStream() {
@@ -1084,7 +1085,7 @@ class OStream {
   llvm::StringRef PendingComment;
   llvm::raw_ostream &OS;
   unsigned IndentSize;
-  unsigned Indent = 0;
+  unsigned Indent;
 };
 
 /// Serializes this Value to JSON, writing it to the provided stream.
diff --git a/llvm/include/llvm/Support/ScopedPrinter.h b/llvm/include/llvm/Support/ScopedPrinter.h
index f6fd2671e812f..134ce1af80673 100644
--- a/llvm/include/llvm/Support/ScopedPrinter.h
+++ b/llvm/include/llvm/Support/ScopedPrinter.h
@@ -399,6 +399,15 @@ class LLVM_ABI ScopedPrinter {
     printString(Label, to_string(Value));
   }
 
+  virtual void printObject(StringRef Label, const json::Value &Value) {
+    std::string PrettyValue;
+    raw_string_ostream PrettyStream(PrettyValue);
+    json::OStream(PrettyStream, 2, getIndentLevel()).value(Value);
+    startLine() << Label << ": "
+                << PrettyValue.substr(PrettyValue.find_first_not_of(" "))
+                << "\n";
+  }
+
   virtual void objectBegin() { scopedBegin('{'); }
 
   virtual void objectBegin(StringRef Label) { scopedBegin(Label, '{'); }
@@ -672,6 +681,10 @@ class JSONScopedPrinter : public ScopedPrinter {
     JOS.attribute(Label, Value);
   }
 
+  void printObject(StringRef Label, const json::Value &Value) override {
+    JOS.attribute(Label, Value);
+  }
+
   void objectBegin() override {
     scopedBegin({Scope::Object, ScopeKind::NoAttribute});
   }
diff --git a/llvm/unittests/Support/ScopedPrinterTest.cpp b/llvm/unittests/Support/ScopedPrinterTest.cpp
index d2b0d643a0be9..e38b07a5ff72b 100644
--- a/llvm/unittests/Support/ScopedPrinterTest.cpp
+++ b/llvm/unittests/Support/ScopedPrinterTest.cpp
@@ -1174,6 +1174,38 @@ TEST_F(ScopedPrinterTest, PrintObject) {
   verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
 }
 
+TEST_F(ScopedPrinterTest, PrintJSONObject) {
+  auto PrintFunc = [](ScopedPrinter &W) {
+    W.printObject("Object",
+                  json::Value(json::Object(
+                      {{"Key", "Value"}, {"Key2", json::Array{1, 1, 2, 3}}})));
+  };
+
+  const char *ExpectedOut = R"(Object: {
+  "Key": "Value",
+  "Key2": [
+    1,
+    1,
+    2,
+    3
+  ]
+}
+)";
+
+  const char *JSONExpectedOut = R"({
+  "Object": {
+    "Key": "Value",
+    "Key2": [
+      1,
+      1,
+      2,
+      3
+    ]
+  }
+})";
+  verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
+}
+
 TEST_F(ScopedPrinterTest, StartLine) {
   auto PrintFunc = [](ScopedPrinter &W) {
     W.startLine() << "|";



More information about the llvm-commits mailing list