Last active
November 25, 2020 13:06
-
-
Save vzsg/8a2ab5089e522787ec87c5e2ceb003e0 to your computer and use it in GitHub Desktop.
Automatically encoding data to JSON with Leaf (for embedding into scripts)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Leaf | |
import Foundation | |
final class JSONTag: TagRenderer { | |
private let encoder = JSONEncoder() | |
func render(tag: TagContext) throws -> EventLoopFuture<TemplateData> { | |
try tag.requireNoBody() | |
try tag.requireParameterCount(1) | |
let json = try encoder.encode(tag.parameters[0]) | |
return tag.future(TemplateData.string(String(data: json, encoding: .utf8) ?? "")) | |
} | |
} | |
extension TemplateData: Encodable { | |
public func encode(to encoder: Encoder) throws { | |
if isNull { | |
var svc = encoder.singleValueContainer() | |
try svc.encodeNil() | |
return | |
} | |
if let array = self.array { | |
var ukc = encoder.unkeyedContainer() | |
try ukc.encode(contentsOf: array) | |
return | |
} | |
if let dict = self.dictionary { | |
var kvc = encoder.container(keyedBy: String.self) | |
try dict.forEach { | |
try kvc.encode($1, forKey: $0) | |
} | |
} | |
// FIXME: this will encode the String "5" as the number 5. This seems | |
// to be less harmful than encoding everything as Strings... | |
// There seems to be no way around the fuzziness of TemplateData. | |
if let int = self.int { | |
var svc = encoder.singleValueContainer() | |
try svc.encode(int) | |
return | |
} | |
if let double = self.double { | |
var svc = encoder.singleValueContainer() | |
try svc.encode(double) | |
return | |
} | |
if let string = self.string { | |
var svc = encoder.singleValueContainer() | |
try svc.encode(string) | |
return | |
} | |
if let data = self.data, let string = String(data: data, encoding: .utf8) { | |
var svc = encoder.singleValueContainer() | |
try svc.encode(string) | |
return | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ... | |
var leafTag = LeafTagConfig.default() | |
leafTag.use(JSONTag(), as: "json") | |
services.register(leafTag) | |
// ... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
extension String: CodingKey { | |
public init?(stringValue: String) { | |
self.init(stringLiteral: stringValue) | |
} | |
public init?(intValue: Int) { | |
self.init(intValue) | |
} | |
public var stringValue: String { | |
return self | |
} | |
public var intValue: Int? { | |
return Int(self) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ... | |
router.get("jsonleaf") { req -> Future<View> in | |
struct Context: Encodable { | |
let params: ChartParams | |
} | |
struct ChartParams: Encodable { | |
let labels: [String] | |
let values: [[Int]] | |
} | |
let context = Context(params: ChartParams(labels: ["Jan", "Feb", "Mar"], values: [[1,3,4], [2,3,4], [5,4,3]])) | |
return try req.view() | |
.render("test", context) | |
} | |
// ... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>JSON tag example</title> | |
</head> | |
<body> | |
<h1>Here's some JSON data</h1> | |
<pre>#json(params)</pre> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment