Skip to content

JSON

JSON is an integral part of Vapor. It powers Vapor's Config and is easy to use in both requests and responses.

Request

JSON is automatically available in request.data alongside Form URL Encoded, Form Data, and Query data. This allows you to focus on making a great API, not worrying about what content types data will be sent in.

drop.get("hello") { request in
    guard let name = request.data["name"]?.string else {
        throw Abort(.badRequest)
    }
    return "Hello, \(name)!"
}

This will return a greeting for any HTTP method or content type that the name is sent as, including JSON.

JSON Only

To specifically target JSON, use the request.json property.

drop.post("json") { request in
    guard let name = request.json?["name"]?.string else {
        throw Abort(.badRequest)
    }

    return "Hello, \(name)!"
}

The above snippet will only work if the request is sent with JSON data.

Response

To respond with JSON, simply create a JSON object and add values to it.

drop.get("version") { request in
    var json = JSON()
    try json.set("version", 1.0)
    return json
}

Convertible

Making your classes and structs JSON convertible is a great way to interact with APIs in an organized and DRY way.

Representable

When something conforms to JSONRepresentable, it can be converted into JSON.

extension User: JSONRepresentable {
    func makeJSON() throws -> JSON {
        var json = JSON()
        try json.set("id", id)
        try json.set("name", name)
        try json.set("age", age)
        return json
    }
}

Now you can simply return user.makeJSON() in your routes.

drop.get("users", User.parameter) { req in
    let user = try req.parameters.next(User.self)
    return try user.makeJSON()
}

You can even go a step further and conform your model to ResponseRepresentable. Since it's already JSONRepresentable you will get the conformance for free.

extension User: ResponseRepresentable { }

Now you can return the model by itself. It will automatically call .makeJSON().

drop.get("users", User.parameter) { req in
    let user = try req.parameters.next(User.self)
    return try user
}

Initializable

When something conforms to JSONInitializable, it can be created from JSON.

extension User: JSONInitializable {
    convenience init(json: JSON) throws {
        try self.init(
            name: json.get("name"),
            age: json.get("age")
        )
    }
}

Now you can simply call User(json: ...) to create a user from JSON.

drop.post("users") { req in
    guard let json = req.json else {
        throw Abort(.badRequest)
    }

    let user = try User(json: json)
    try user.save()
    return user
}