This repository has been archived by the owner on Sep 3, 2018. It is now read-only.
forked from hebertialmeida/ModelGen
-
Notifications
You must be signed in to change notification settings - Fork 1
/
JsonParser.swift
121 lines (103 loc) · 3.65 KB
/
JsonParser.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//
// JsonParser.swift
// ModelGen
//
// Created by Heberti Almeida on 2017-05-10.
// Copyright © 2017 ModelGen. All rights reserved.
//
import Foundation
import StencilSwiftKit
import PathKit
public typealias JSON = [String: Any]
public final class JsonParser {
public var json: JSON = [:]
public var properties = [SchemaProperty]()
public var customKeyProperties: [SchemaProperty] {
return properties.filter { $0.hasCustomJsonKey }
}
public var nonCustomKeyProperties: [SchemaProperty] {
return properties.filter { !$0.hasCustomJsonKey }
}
public var nonOptionalProperties: [SchemaProperty] {
return properties.filter { !$0.isOptional }
}
public var optionalProperties: [SchemaProperty] {
return properties.filter { $0.isOptional }
}
public var immutableProperties: [SchemaProperty] {
return properties.filter { !$0.isMutable }
}
public var mutableProperties: [SchemaProperty] {
return properties.filter { $0.isMutable }
}
public init() {}
public func parseFile(at path: Path) throws {
currentFile = path
do {
guard let json = try JSONSerialization.jsonObject(with: try path.read(), options: []) as? JSON else {
throw JsonParserError.invalidFile(reason: "Invalid structure.")
}
self.json = json
} catch let error as JsonParserError {
throw error
} catch let error {
throw JsonParserError.invalidFile(reason: error.localizedDescription)
}
}
}
// MARK: Parser
func render(output: OutputDestination, template: String, lang: String, path: Path) throws {
guard path.isDirectory else {
do {
try parse(output: output, template: template, lang: lang, path: path)
} catch let error {
printError(error.localizedDescription, showFile: true)
}
printSuccess("Finished generation.")
exit(0)
}
let paths = try path.children().filter { $0.extension == "json" }
paths.forEach { path in
do {
try parse(output: output, template: template, lang: lang, path: path)
} catch let error {
printError(error.localizedDescription, showFile: true)
}
}
printSuccess("Finished generation of \(paths.count) files.")
}
/// Parse specs and generate files based on json
///
/// - Parameters:
/// - output: Output destination of generated files
/// - template: Stencil template
/// - lang: Language to generate files
/// - path: Spec path, folder or file.json
/// - Throws: Error if something happens
func parse(output: OutputDestination, template: String, lang: String, path: Path) throws {
let parser = JsonParser()
var finalOutput = output
jsonAbsolutePath = Path(NSString(string: path.description).deletingLastPathComponent)
do {
try parser.parseFile(at: path)
let language = Language(rawValue: lang) ?? .swift
let tempatePath = try validate(template)
let template = try StencilSwiftTemplate(templateString: tempatePath.read(), environment: stencilSwiftEnvironment())
let context = try parser.stencilContextFor(language)
let enriched = try StencilContext.enrich(context: context, parameters: [])
let rendered = try template.render(enriched)
let out = Path(output.description)
guard out.isDirectory else {
output.write(content: rendered, onlyIfChanged: true)
return
}
guard let title = parser.json["title"] as? String else {
throw JsonParserError.missingTitle
}
let finalPath = Path(output.description) + "\(title.uppercaseFirst() + language.fileExtension)"
finalOutput = .file(finalPath)
finalOutput.write(content: rendered, onlyIfChanged: true)
} catch let error {
printError(error.localizedDescription, showFile: true, file: path.description)
}
}