-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Issue Type
TLDR; Quicktype is generating invalid Swift under the Swift 6 language compiler
Generated Swift helper classes (JSONCodingKey, JSONAny, JSONNull) don't compile under Swift 6 strict concurrency, even when --sendable is passed.
Context (Environment, Version, Language)
Input Format: JSON Schema (--src-lang schema)
Output Language: Swift
CLI, npm, or app.quicktype.io: CLI
Version: 23.2.6
Description
When generating Swift code with --sendable and --struct-or-class struct, the generated model structs correctly gain Sendable conformance. However, the helper classes at the bottom of the output (JSONNull, JSONCodingKey, JSONAny) are not updated for Swift 6 strict concurrency:
JSONCodingKeyis a non-final class — Swift 6 errors withnon-final class 'JSONCodingKey' cannot conform to 'Sendable'JSONAnystoresAnywhich is notSendable— needs@unchecked Sendableandnonisolated(unsafe)(related: [FEATURE]: Swift - Sendable JSONAny #2598)JSONNulluses deprecatedhashValue(minor, but warning noise)
This makes the output unusable with swift-tools-version: 6.0 packages out of the box.
Input Data
Any JSON Schema that produces additionalProperties / untyped fields triggers JSONAny usage. Minimal example:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Example",
"type": "object",
"properties": {
"data": {
"type": "object",
"additionalProperties": true
}
}
}Expected Behaviour / Output
When --sendable is passed, all generated types — including JSONCodingKey, JSONNull, and JSONAny — should compile cleanly under Swift 6 strict concurrency (swift-tools-version: 6.0).
Specifically:
JSONCodingKeyshould befinal class JSONCodingKey: CodingKey, SendableJSONAnyshould be marked@unchecked Sendable(since it wrapsAny)JSONNullshould usehash(into:)instead of deprecatedhashValue
Current Behaviour / Output
error: non-final class 'JSONCodingKey' cannot conform to 'Sendable'; use '@unchecked Sendable'
warning: 'Hashable.hashValue' is deprecated as a protocol requirement; conform type 'JSONNull' to 'Hashable' by implementing 'hash(into:)' instead
The generated struct models are correctly Sendable, but the helper classes break the build.
Steps to Reproduce
npm install -g quicktype- Save the minimal JSON Schema above as
example.json - Run:
quicktype \ --lang swift \ --src-lang schema \ --src example.json \ --access-level public \ --struct-or-class struct \ --coding-keys \ --sendable \ -o Models.swift
- Create a Swift package with
swift-tools-version: 6.0and try to build
mkdir MyPackage && cd MyPackage
swift package init --type library --name MyPackage
sed -i '' 's/swift-tools-version: .*/swift-tools-version: 6.0/' Package.swift
cp ../Models.swift Sources/MyPackage/Models.swift
swift buildPossible Solution
I'm currently working around this by making the following changes with sed after generation:
- Emit
final class JSONCodingKey: CodingKey, Sendableinstead ofclass JSONCodingKey: CodingKey - Emit
public class JSONAny: Codable, @unchecked Sendablewithnonisolated(unsafe)on thevalueproperty - Replace
public var hashValue: Intwithpublic func hash(into hasher: inout Hasher) {}onJSONNull
For point 2 this is would be safer as an enum for future extensibility
public enum JSONValue: Codable, Sendable {
case null
case bool(Bool)
case int(Int64)
case double(Double)
case string(String)
case array([JSONValue])
case object([String: JSONValue])
}