Reputation: 179
Recently I'm developing API parts using GraphQL.
When I call API, I need to generate a query from structure like this.
// from this model
struct ModelA {
let id: String
let title: String
....
}
// to this query
query {
id
title
}
If I have an instance of ModelA, I can reflect properties from instance using Mirror.
But I don't want to make the instance in this case and I don't want to make the properties to variables because I need to use this model for response.
Additionally class_copyPropertyList is a good solution if the model is NSObject class. However in this case this is a structure in swift.
Is this possible? I appreciate your help in advance.
Upvotes: 1
Views: 869
Reputation: 1490
try this
extension Encodable {
func query() -> String? {
guard let encodeData: Data = try? JSONEncoder().encode(self) else { return nil }
guard let jsonRepresentation: [String: Any] = try? JSONSerialization.jsonObject(with: encodeData, options: []) as? [String: Any] else { return nil }
let keys: String = jsonRepresentation.map{ $0.key }.joined(separator: " ")
return "query { " + keys + " }"
}
}
struct ModelA: Encodable {
let id: String
let title: String
}
let model = ModelA(id: "abc123", title: "Model title")
if let query = model.query() {
print(query)
}
EDIT
// query function in Encodable extension stays the same
protocol Querable: Encodable {
static var dummy: Encodable { get }
}
extension Querable {
static var query: String? {
return self.dummy.query()
}
}
struct ModelA: Querable {
let id: String
let title: String
static var dummy: Encodable {
return ModelA(id: "", title: "")
}
}
if let query = ModelA.query {
print(query)
}
Upvotes: 1
Reputation: 5073
Unfortunately you're not going to be able to do that with structs. You can, however, do something like this.
protocol Queryable {
static var queryableProperties: [String] { get }
}
extension Queryable {
static func makeQuery() -> String {
return "query {\n"
+ queryableProperties
.map { " \($0)" }
.joined(separator: "\n")
+ "\n}"
}
}
struct Dog {
let name: String
let age: Int
}
extension Dog: Queryable {
static var queryableProperties: [String] {
return ["name", "age"]
}
}
struct Person {
let firstName: String
let lastName: String
}
extension Person: Queryable {
static var queryableProperties: [String] {
return ["firstName", "lastName"]
}
}
print(Person.makeQuery())
print(Dog.makeQuery())
Which prints:
query {
firstName
lastName
}
query {
name
age
}
Upvotes: 0