                             string += "var \(key.coolie_lowerCamelCase): \(key.capitalized)\n"
                         }
                     } else {
-                        indentLevel(level + 1)
+                        indent(with: level + 1, into: &string)
                         string += "var \(key.coolie_lowerCamelCase): \(value.type)\n"
                     }
                 }
             }
             // generate method
-            indentLevel(level + 1)
+            indent(with: level + 1, into: &string)
             let initArgumentLabel = argumentLabel ?? "_"
             string += "init?(\(initArgumentLabel) info: \(jsonDictionaryName)) {\n"
             let trueArgumentLabel = argumentLabel.flatMap({ "\($0): " }) ?? ""

extension Coolie.Value {

    func generateClass(fromLevel level: Int = 0, modelName: String? = nil, argumentLabel: String? = nil, jsonDictionaryName: String? = nil, debug: Bool, into string: inout String) {
        func indentLevel(_ level: Int) {
            for _ in 0..<level {
                string += "\t"
            }
        }
        let jsonDictionaryName = jsonDictionaryName ?? "[String: Any]"
        switch self {
        case .bool, .number, .string, .url, .null:
            break
        case .dictionary(let info):
            // struct name
            indentLevel(level)
            string += "class \(modelName ?? "Model") {\n"
            // properties
            for key in info.keys.sorted() {
                if let value = info[key] {
                    if value.isDictionaryOrArray {
                        value.generateClass(fromLevel: level + 1, modelName: key.capitalized, argumentLabel: argumentLabel, jsonDictionaryName: jsonDictionaryName, debug: debug, into: &string)
                        indentLevel(level + 1)
                        if value.isArray {
                            if case .array(_, let values) = value, let unionValue = unionValues(values) {
                                if case .null(let optionalValue) = unionValue {

                                if case .null(let optionalValue) = unionValue {
                                    if let value = optionalValue {
                                        if value.isDictionary {
                                            indent(with: level + 2, into: &string)
                                            string += "guard let \(key.coolie_lowerCamelCase)JSONArray = info[\"\(key)\"] as? [\(jsonDictionaryName)?] else { "
                                            string += debug ? "print(\"Not found array key: \(key)\"); return nil }\n" : "return nil }\n"
                                            indent(with: level + 2, into: &string)
                                            string += "let \(key.coolie_lowerCamelCase) = \(key.coolie_lowerCamelCase)JSONArray.map({ $0.flatMap({ \(key.capitalized.coolie_dropLastCharacter)(\(trueArgumentLabel)$0) }) })\n"
                                        } else {
                                            indent(with: level + 2, into: &string)
                                            string += "guard let \(key.coolie_lowerCamelCase) = info[\"\(key)\"] as? [\(value.type)?] else { "
                                            string += debug ? "print(\"Not found array key: \(key)\"); return nil }\n" : "return nil }\n"
                                        }
                                    } else {
                                        indent(with: level + 2, into: &string)
                                        let type = "UnknownType"
                                        string += "let \(key.coolie_lowerCamelCase) = info[\"\(key)\"] as? \(type)\n"
                                    }
                                } else {
                                    if unionValue.isDictionary {
                                        indent(with: level + 2, into: &string)
                                        string += "guard let \(key.coolie_lowerCamelCase)JSONArray = info[\"\(key)\"] as? [\(jsonDictionaryName)] else { "
                                        string += debug ? "print(\"Not found array key: \(key)\"); return nil }\n" : "return nil }\n"
                                        indent(with: level + 2, into: &string)
                                        string += "let \(key.coolie_lowerCamelCase) = \(key.coolie_lowerCamelCase)JSONArray.map({ \(key.capitalized.coolie_dropLastCharacter)(\(trueArgumentLabel)$0) }).flatMap({ $0 })\n"
                                    } else {
                                        indent(with: level + 2, into: &string)
                                        string += "guard let \(key.coolie_lowerCamelCase) = info[\"\(key)\"] as? [\(unionValue.type)] else { "
                                        string += debug ? "print(\"Not found array key: \(key)\"); return nil }\n" : "return nil }\n"
                                    }
                                }
                            } else {
                                indent(with: level + 2, into: &string)
                                string += "guard let \(key.coolie_lowerCamelCase)JSONArray = info[\"\(key)\"] as? [\(jsonDictionaryName)] else { "
                                string += debug ? "print(\"Not found array key: \(key)\"); return nil }\n" : "return nil }\n"
                                indent(with: level + 2, into: &string)
                                string += "let \(key.coolie_lowerCamelCase) = \(key.coolie_lowerCamelCase)JSONArray.map({ \(key.capitalized.coolie_dropLastCharacter)(\(trueArgumentLabel)$0) }).flatMap({ $0 })\n"
                            }
                        }
                    } else {
                        indent(with: level + 2, into: &string)
                        if case .null(let optionalValue) = value {
                            let type: String
                            if let value = optionalValue {
