If I build a Swift dictionary, i.e. [String: Any] how can I return that as JSON? I tried this, but it gives me the error: Argument labels '(node:)' do not match any available overloads.
drop.get("test") { request in
var data: [String: Any] = [:]
data["name"] = "David"
data["state"] = "CA"
return try JSON(node: data)
}
Convoluted as heck, but this allows you to use [String:Any].makeNode(), as long as the internals are NodeRepresentable, NSNumber based, or NSNull :) --
import Node
enum NodeConversionError : LocalizedError {
case invalidValue(String,Any)
var errorDescription: String? {
switch self {
case .invalidValue(let key, let value): return "Value for \(key) is not NodeRepresentable - " + String(describing: type(of: value))
}
}
}
extension NSNumber : NodeRepresentable {
public func makeNode(context: Context = EmptyNode) throws -> Node {
return Node.number(.double(Double(self)))
}
}
extension NSString : NodeRepresentable {
public func makeNode(context: Context = EmptyNode) throws -> Node {
return Node.string(String(self))
}
}
extension KeyAccessible where Key == String, Value == Any {
public func makeNode(context: Context = EmptyNode) throws -> Node {
var mutable: [String : Node] = [:]
try allItems.forEach { key, value in
if let _ = value as? NSNull {
mutable[key] = Node.null
} else {
guard let nodeable = value as? NodeRepresentable else { throw NodeConversionError.invalidValue(key, value) }
mutable[key] = try nodeable.makeNode()
}
}
return .object(mutable)
}
public func converted<T: NodeInitializable>(to type: T.Type = T.self) throws -> T {
return try makeNode().converted()
}
}
With that header you can:
return try JSON(node: data.makeNode())
JSON cannot be initialized from a [String : Any] dictionary because Any is not convertible to Node.
There are only a limited number of types that Node can be. (See Node source). If you know your objects are all going to be the same type, use a dictionary that only allows that type. So for your example, [String : String].
If you're going to be getting data from the request, you can try using request.json as is used in the documentation here.
Another (possibly better) solution would be to make your dictionary [String: Node] and then you can include any type that conforms to Node. You may have to call the object's makeNode() function to add it to the dictionary though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With