Skip to content

Commit

Permalink
Support unicode sequence escaping
Browse files Browse the repository at this point in the history
  • Loading branch information
luin committed Dec 22, 2022
1 parent 843456f commit 320e944
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import PackageDescription
let package = Package(
name: "SwiftJSONFormatter",
platforms: [
.macOS(.v10_13),
.macOS(.v10_15),
.iOS(.v12),
.tvOS(.v12),
.watchOS(.v5)
Expand Down
6 changes: 3 additions & 3 deletions Sources/SwiftJSONFormatter/ArrayIterator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ class ArrayIterator<T> {
self.array = array
}

func peekNext() -> T? {
if head + 1 < array.count {
return array[head + 1]
func peekNext(n: Int = 1) -> T? {
if head + n < array.count {
return array[head + n]
}
return nil
}
Expand Down
38 changes: 27 additions & 11 deletions Sources/SwiftJSONFormatter/SwiftJSONFormatter.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation

public struct SwiftJSONFormatter {
public private(set) var text = "Hello, World!"

private static func format(_ value: String, indent: String, newLine: String, separator: String) -> String {
private static func format(_ value: String, indent: String, newLine: String, separator: String, unescapeUnicodeSequence: Bool) -> String {
var formatted = ""

let chars = ArrayIterator(Array(value))
Expand All @@ -27,7 +27,7 @@ public struct SwiftJSONFormatter {
formatted.append(newLine)
formatted += "\(String(repeating: indent, count: indentLevel))\(char)"
case "\"":
let string = consumeString(chars)
let string = consumeString(chars, unescapeUnicodeSequence: unescapeUnicodeSequence)
formatted.append(string)
case ",":
consumeWhitespaces(chars)
Expand All @@ -52,12 +52,12 @@ public struct SwiftJSONFormatter {
return formatted
}

public static func beautify(_ value: String, indent: String = " ") -> String {
format(value, indent: indent, newLine: "\n", separator: " ")
public static func beautify(_ value: String, indent: String = " ", unescapeUnicodeSequence: Bool = false) -> String {
format(value, indent: indent, newLine: "\n", separator: " ", unescapeUnicodeSequence: unescapeUnicodeSequence)
}

public static func minify(_ value: String) -> String {
format(value, indent: "", newLine: "", separator: "")
public static func minify(_ value: String, unescapeUnicodeSequence: Bool = false) -> String {
format(value, indent: "", newLine: "", separator: "", unescapeUnicodeSequence: unescapeUnicodeSequence)
}

private static func consumeWhitespaces(_ iter: ArrayIterator<String.Element>) {
Expand All @@ -70,7 +70,22 @@ public struct SwiftJSONFormatter {
}
}

private static func consumeString(_ iter: ArrayIterator<String.Element>) -> String {
private static func performUnescaping(_ jsonString: String, unescapeUnicodeSequence: Bool) -> String {
if unescapeUnicodeSequence {
let decoder = JSONDecoder()
if let data = jsonString.data(using: .utf8), let result = try? decoder.decode(String.self, from: data) {
let encoder = JSONEncoder()
encoder.outputFormatting = .withoutEscapingSlashes
if let encoded = try? encoder.encode(result), let encodedString = String(data: encoded, encoding: .utf8) {
return encodedString
}
}
}

return jsonString
}

private static func consumeString(_ iter: ArrayIterator<String.Element>, unescapeUnicodeSequence: Bool) -> String {
var string = "\""
var escaping = false
while true {
Expand All @@ -88,13 +103,14 @@ public struct SwiftJSONFormatter {
escaping = true
}
if char == "\"" {
return string
return performUnescaping(string, unescapeUnicodeSequence: unescapeUnicodeSequence)
}
}
} else {
break
}
}
return string

return performUnescaping(string, unescapeUnicodeSequence: unescapeUnicodeSequence)
}
}
33 changes: 33 additions & 0 deletions Tests/SwiftJSONFormatterTests/SwiftJSONFormatterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,37 @@ final class SwiftJSONFormatterTests: XCTestCase {
"contains\"", "\\\"quotes\n"]
"""#), #"["string","contains\"","\\\"quotes\n"]"#)
}

func testUnicodeEscaping() {
XCTAssertEqual(SwiftJSONFormatter.minify(
#"["15\u00f8C"]"#,
unescapeUnicodeSequence: false
),
#"["15\u00f8C"]"#
)
XCTAssertEqual(SwiftJSONFormatter.minify(
#"["15\u00f8C"]"#,
unescapeUnicodeSequence: true
),
#"["15øC"]"#
)
XCTAssertEqual(SwiftJSONFormatter.minify(
#"["Bien pr\u00e9parer votre s\u00e9jour"]"#,
unescapeUnicodeSequence: true
),
#"["Bien préparer votre séjour"]"#
)
XCTAssertEqual(SwiftJSONFormatter.minify(
#"["\u4F60\u597D\n \uD83D\uDE04\uD83D\uDE04\uD834\uDF06"]"#,
unescapeUnicodeSequence: true
),
#"["你好\n 😄😄𝌆"]"#
)
XCTAssertEqual(SwiftJSONFormatter.minify(
#"["https://example.com"]"#,
unescapeUnicodeSequence: true
),
#"["https://example.com"]"#
)
}
}

0 comments on commit 320e944

Please sign in to comment.