Avoid escaping slashes in JSON output (#2205)

Fixes #2204.

Swift's default JSONEncoder output escapes forward slashes, which makes CLI JSON paths and URLs harder to read and copy. This change makes the shared CLI JSON renderer always use .withoutEscapingSlashes and routes machine list --format json through that renderer while preserving its ISO-8601 date encoding.

OpenAI Codex assisted with investigation, implementation, and verification. The final change is limited to JSON rendering behavior and focused regression coverage.

Co-authored-by: taljeon <169621860+taljeon@users.noreply.github.com>
This commit is contained in:
Tal
2026-08-28 16:37:33 -07:00
committed by GitHub
co-authored by taljeon
parent a9a62e28f6
commit d65874da36
3 changed files with 12 additions and 5 deletions
@@ -61,10 +61,8 @@ extension Application {
let printables = machines.map {
PrintableMachine($0, isDefault: $0.id == defaultMachine)
}
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
let data = try encoder.encode(printables)
print(String(decoding: data, as: UTF8.self))
let options = JSONOptions(dateEncodingStrategy: .iso8601)
try Output.emit(Output.renderJSON(printables, options: options))
return
}
@@ -44,7 +44,7 @@ public enum Output {
/// Renders an `Encodable` value as a JSON string.
public static func renderJSON<T: Encodable>(_ value: T, options: JSONOptions = .compact) throws -> String {
let encoder = JSONEncoder()
encoder.outputFormatting = options.outputFormatting
encoder.outputFormatting = options.outputFormatting.union(.withoutEscapingSlashes)
encoder.dateEncodingStrategy = options.dateEncodingStrategy
let data = try encoder.encode(value)
return String(decoding: data, as: UTF8.self)
@@ -163,6 +163,15 @@ struct RenderJSONTests {
#expect(!json.contains("\n"))
}
@Test
func doesNotEscapeSlashes() throws {
let item = TestItem(id: "/foo/bar", name: "https://example.com/path")
let json = try Output.renderJSON(item)
#expect(json.contains("/foo/bar"))
#expect(json.contains("https://example.com/path"))
#expect(!json.contains("\\/"))
}
@Test
func prettyIsMultiLine() throws {
let items = [TestItem(id: "a", name: "b")]