             case .isOptional:
                 switch $0.type.plainType {
                 case let .primitive(p):
-                    lines.append("\(indent2)let \(propertyName) = json[\"\($0.name)\"] as? \(p.name)")
+                    switch p {
+                    case .bool, .int, .double, .string:
+                        lines.append("\(indent2)let \(propertyName) = json[\"\($0.name)\"] as? \(p.name)")
+                    case .url:
+                        lines.append("\(indent2)let \(propertyName)String = json[\"\($0.name)\"] as? String")
+                        lines.append("\(indent2)let \(propertyName) = \(propertyName)String.flatMap({ URL(string: $0) })")
+                    case let .date(type):
+                        switch type {
+                        case .iso8601:
+                            let dateString = "\(propertyName)String"
+                            lines.append("\(indent2)let \(dateString) = json[\"\($0.name)\"] as? String")
+                            lines.append("\(indent2)let \(propertyName) = \(dateString).flatMap({ DateFormatter.iso8601.date(from: $0) })")
+                        case .dateOnly:
+                            let dateString = "\(propertyName)String"
+                            lines.append("\(indent2)let \(dateString) = json[\"\($0.name)\"] as? String")
+                            lines.append("\(indent2)let \(propertyName) = \(dateString).flatMap({ DateFormatter.dateOnly.date(from: $0) })")
+                        case .secondsSince1970:
+                            let dateTimeInterval = "\(propertyName)TimeInterval"
+                            lines.append("\(indent2)let \(dateTimeInterval) = json[\"\($0.name)\"] as? TimeInterval")
+                            lines.append("\(indent2)let \(propertyName) = \(dateTimeInterval).flatMap({ Date(timeIntervalSince1970: $0) })")
+                        }
+                    case .any:
+                        lines.append("\(indent2)let \(propertyName) = json[\"\($0.name)\"]")
+                    case .null: // TODO: null
+                        assertionFailure("null in isOptional")
+                        break
+                    }
                 case let .struct(s):
                     lines.append("\(indent2)let \(propertyName)JSONDictionary = json[\"\($0.name)\"] as? \(meta.jsonDictionaryName)")
                     lines.append("\(indent2)let \(propertyName) = \(propertyName)JSONDictionary.flatMap({ \(s.typeName)(json: $0) })")

        }).map({
            "\($0): \($0)"
        }).joined(separator: ", ")
        lines.append("\(indent2)init(\(arguments))")
        lines.append("\(indent1)}")
        return lines.joined(separator: "\n")
    }

                            lines.append("\(indent2)let \(propertyName) = Date(timeIntervalSince1970: \(dateTimeInterval))")
                        }
                    case .any:
                        lines.append("\(indent2)guard let \(propertyName) = json[\"\($0.name)\"] else { return nil }")
                    case .null:
                        assertionFailure("null for normal")
                        break
                    }
                case let .struct(s):
