Add custom ExtJSON pretty printer to handle Mongo objects

This commit is contained in:
Shadowfacts 2020-08-12 15:59:21 -04:00
parent 54f8236332
commit 45e45a3991
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
5 changed files with 113 additions and 8 deletions

View File

@ -23,6 +23,7 @@
D627CE8824E399F100C39FE5 /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D627CE8624E399F100C39FE5 /* DetailViewController.swift */; };
D627CE8924E399F100C39FE5 /* DetailViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D627CE8724E399F100C39FE5 /* DetailViewController.xib */; };
D627CE8B24E438EE00C39FE5 /* DatabaseCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D627CE8A24E438EE00C39FE5 /* DatabaseCollection.swift */; };
D627CE8D24E4478800C39FE5 /* JSONPrettyPrinter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D627CE8C24E4478800C39FE5 /* JSONPrettyPrinter.swift */; };
D63CDEBE23C837DC0012D658 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63CDEBD23C837DC0012D658 /* AppDelegate.swift */; };
D63CDEC023C837DD0012D658 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D63CDEBF23C837DD0012D658 /* Assets.xcassets */; };
D63CDEC323C837DD0012D658 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D63CDEC123C837DD0012D658 /* MainMenu.xib */; };
@ -107,6 +108,7 @@
D627CE8624E399F100C39FE5 /* DetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = "<group>"; };
D627CE8724E399F100C39FE5 /* DetailViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DetailViewController.xib; sourceTree = "<group>"; };
D627CE8A24E438EE00C39FE5 /* DatabaseCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseCollection.swift; sourceTree = "<group>"; };
D627CE8C24E4478800C39FE5 /* JSONPrettyPrinter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONPrettyPrinter.swift; sourceTree = "<group>"; };
D63CDEBA23C837DC0012D658 /* MongoView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MongoView.app; sourceTree = BUILT_PRODUCTS_DIR; };
D63CDEBD23C837DC0012D658 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
D63CDEBF23C837DD0012D658 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@ -234,6 +236,7 @@
D627CE8A24E438EE00C39FE5 /* DatabaseCollection.swift */,
D6D4665223CB730C00F13B1B /* MongoEvaluator.swift */,
D624090E243903E90020E09F /* ExtendedJSON.swift */,
D627CE8C24E4478800C39FE5 /* JSONPrettyPrinter.swift */,
D6A7D0A22435880700B46857 /* Synax Highlighting */,
D60C863B23CA2DD600C9DB8E /* Windows */,
D60C863C23CA2DDD00C9DB8E /* View Controllers */,
@ -383,6 +386,7 @@
D63CDEBE23C837DC0012D658 /* AppDelegate.swift in Sources */,
D6D4665323CB730C00F13B1B /* MongoEvaluator.swift in Sources */,
D624090F243903E90020E09F /* ExtendedJSON.swift in Sources */,
D627CE8D24E4478800C39FE5 /* JSONPrettyPrinter.swift in Sources */,
D63CDF3823C8381A0012D658 /* MongoController.swift in Sources */,
D60C863923CA2DD100C9DB8E /* ServerConnectWindowController.swift in Sources */,
D63CDF3723C8381A0012D658 /* Node.swift in Sources */,

View File

@ -19,6 +19,10 @@ struct ExtendedJSON {
return ["$oid": id]
}
context.setObject(objectId, forKeyedSubscript: "ObjectId" as NSString)
let date: @convention(block) (String) -> [String: String] = { (date) in
return ["$date": date]
}
context.setObject(date, forKeyedSubscript: "Date" as NSString)
return context
}()
@ -44,10 +48,4 @@ struct ExtendedJSON {
return doc
}
static func prettify(_ string: String) -> String? {
context.setObject(string, forKeyedSubscript: "value" as NSString)
let command = "JSON.stringify(JSON.parse(value), null, 4)"
return context.evaluateScript(command)?.toString()
}
}

View File

@ -0,0 +1,102 @@
//
// JSONPrettyPrinter.swift
// MongoView
//
// Created by Shadowfacts on 8/12/20.
// Copyright © 2020 Shadowfacts. All rights reserved.
//
import Foundation
class JSONPrettyPrinter {
let options: Options
private var strings = [String]()
private var currentIndent = ""
init(options: Options) {
self.options = options
}
func prettify(_ string: String) throws -> String {
let object = try JSONSerialization.jsonObject(with: string.data(using: .utf8)!, options: [])
doPrettify(object)
return strings.joined(separator: "")
}
private func indent() {
currentIndent += "\t"
}
private func outdent() {
currentIndent = String(currentIndent.dropLast())
}
private func doPrettify(_ object: Any) {
if let dict = object as? [String: Any] {
if options.contains(.convertMongoObjects) && tryPrettifyMongoObject(dict) {
return
}
indent()
strings.append("{\n")
for (index, k) in dict.keys.sorted().enumerated() {
strings.append("\(currentIndent)\"\(escape(k))\"")
strings.append(": ")
doPrettify(dict[k]!)
if index != dict.count - 1 {
strings.append(",\n")
}
}
outdent()
strings.append("\n\(currentIndent)}")
} else if let arr = object as? [Any] {
indent()
strings.append("[\n")
for (index, v) in arr.enumerated() {
strings.append(currentIndent)
doPrettify(v)
if index != arr.count - 1 {
strings.append(",\n")
}
}
outdent()
strings.append("\n\(currentIndent)]")
} else if let str = object as? String {
strings.append("\"\(escape(str))\"")
} else if let bool = object as? Bool {
strings.append(bool.description)
} else if let num = object as? NSNumber {
strings.append(num.description)
} else if object is NSNull {
strings.append("null")
} else {
fatalError("unhandled object type: \(String(describing: object))")
}
}
private func tryPrettifyMongoObject(_ dict: [String: Any]) -> Bool {
guard dict.count == 1 else { return false }
if let value = dict["$oid"] as? String {
strings.append("ObjectId(\"\(value)\")")
return true
}
if let value = dict["$date"] as? String {
strings.append("Date(\"\(value)\")")
return true
}
return false
}
private func escape(_ str: String) -> String {
return str.replacingOccurrences(of: "\"", with: "\\\"")
}
}
extension JSONPrettyPrinter {
struct Options: OptionSet {
let rawValue: Int
static let convertMongoObjects = Options(rawValue: 1 << 0)
}
}

View File

@ -37,7 +37,9 @@ class EditDocumentViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
editorTextView.string = ExtendedJSON.prettify(document.extendedJSON) ?? document.extendedJSON
let printer = JSONPrettyPrinter(options: .convertMongoObjects)
editorTextView.string = (try? printer.prettify(document.extendedJSON)) ?? document.extendedJSON
editorTextView.isAutomaticQuoteSubstitutionEnabled = false
}

View File

@ -19,7 +19,6 @@ class JavaScriptEditorView: NSTextView {
super.string
}
set {
isRehighlighting = true
super.string = newValue
rehighlight()
}