Server-Side Swift VaporでネストしたContentや配列のValidation方法

Last Updated on 2023年9月23日 by lemonade

概要

公式ドキュメントに以下のようなオブジェクトの配列やネストがあるJSONをvalidateする方法について説明します。

{
    username: string.
    age: number,
    detail: {
        blogURL: string
    },
    favorites: {
        genre: String,
        name: String
    }[]
}

Vaporの公式ドキュメントを探したのですが、この際にdetailやfavoritesを検証する方法が見当たりません。

結論

以下のSwiftのContentに準拠した構造体があるとします。

import Vapor

struct User: Content {
    var username: String
    var age: Int
    var detail: Detail
    var favorites: [Favorite]

    struct Detail: Content {
        var blogURL: String
    }
    struct Favorite: Content {
        var genre: String
        var name: String
    }
}

その際には、以下のようなValidationを追加してあげればOKです

import Vapor

extension User: Validatable {
    static func validations(_ validations: inout Validations) {
        validations.add("username", as: String.self, is: .count(0...1_000))
        validations.add("age", as: Int.self, is: .range(0...2_00))
        validations.add("detail") { detail in
            detail.add("blogURL", as: String.self, is: .url)
        }
        validations.add(each: "favorites") { (i, favorite) in
            favorite.add("genre", as: String.self, is: .count(1...1_000)
            favorite.add("name", as: String.self, is: .count(1...1_000)
        }
    }
}

余談

User.Detailのvalidationを複数箇所から使う場合には以下のように共通化も可能です。

import Vapor

extension User.Detail: Validatable {
    static func validations(_ validations: inout Validations) {
        validations.add("blogURL", as: String.self, is: .url)
    }
}

extension Favorite: Validatable {
    static func validations(_ validations: inout Validations) {
        validations.add("genre", as: String.self, is: .count(1...1_000)
        validations.add("name", as: String.self, is: .count(1...1_000)
    }
}

extension User: Validatable {
    static func validations(_ validations: inout Validations) {
        validations.add("username", as: String.self, is: .count(0...1_000))
        validations.add("age", as: Int.self, is: .range(0...200))
        validations.add("detail", User.Detail.validations)
        validations.add(each: "favorites", ({ Favorite.validations(&$1) }))
        validations.add("favorites", as: [Favorite.self], is: !.empty)
    }
}

参考

Vapor ValidationTests.swift

Leave a Comment

CAPTCHA