Back to OSS
Swift Package LLM / AI
swift-structured-data
外部由来の JSON / YAML / XML を Swift の型システムへ安全に変換するレイヤー
Swift
jsonyamltype-safe
swift-structured-data
外部システム由来の動的な構造化データ(JSON ほか)を、Swift の型システムへ安全に変換するレイヤー。
「正しく読む」層と「型へ変換する」層を分離し、数値の精度や順序を失わずに Codable へ橋渡しする。
設計の全体像は DESIGN.md を参照。
特徴
- 任意精度を壊さない数値モデル — JSON number を生の十進文字列で保持し、要求された型へ遅延変換
- 規定プロトコル中心の依存設計 — 消費者は
any StructuredDecodingを注入で受け、具象パーサに依存しない - フォーマット非依存の単一バックボーン — カスタム
Decoder/Encoderを 1 度実装し全フォーマットで再利用 - 探索アクセサ —
value.user.name.stringの動的アクセスと、型安全なdecode(_:)の二層 - 寛容デコードをフィールド単位でオプトイン —
@Default/@LossyArray/@LosslessValue - ストリーミング部分デコード — LLM のトークン逐次出力から途中状態を抽出
- 公式適合性スイートで検証 — nst/JSONTestSuite を同梱して
y_/n_/i_を網羅
使い方
デコード / エンコード
import JSONParsing
struct Config: Codable { var retries: Int; var hosts: [String] }
let config = try JSONDecoder().decode(Config.self, from: data)
let data = try JSONEncoder().encode(config)
規定プロトコルへの注入(依存性逆転)
import StructuredDataCore // ライブラリは Core にのみ依存
struct APIClient {
let decoder: any StructuredDecoding
func parse<T: Decodable>(_ type: T.Type, from data: Data) throws -> T {
try decoder.decode(type, from: data)
}
}
// 合成ルート(アプリ)だけが具象を選ぶ
let client = APIClient(decoder: JSONDecoder())
動的な探索
let value = try JSONParser().parse(data)
value.user.name.string // String?
value.items[0].id.int // Int?
value["count", as: Int.self] // Int?
寛容デコード
struct Settings: Codable {
@DefaultFalse var verbose: Bool
@DefaultEmptyArray<String> var tags: [String]
@LossyArray var ids: [Int] // 壊れた要素を捨てる
@LosslessValue var port: Int // "8080" でも 8080 でも受ける
}
ストリーミング
var parser = StreamingJSONParser()
parser.consume(#"{"name":"Ad"#)
parser.snapshot().name.string // "Ad"
parser.consume(#"a"}"#)
parser.snapshot().name.string // "Ada"
モジュール
| モジュール | 役割 |
|---|---|
StructuredDataCore |
規定プロトコル・中立 DOM・Decoder/Encoder バックボーン・property wrapper |
JSONParsing |
RFC 8259 パーサ/シリアライザ・ストリーミング |
YAMLParsing |
YAML 1.2 Core サブセットのパーサ(block/flow・block scalar・multi-doc・Norway 修正) |
YAML はフルスペック(anchor/alias・tag・複合キー)未対応。実装状況とテスト計測は DESIGN.md を参照。
ライセンス
MIT