feat(kotlin): Support for date and datetime from JSON schema#2845
Merged
Conversation
Contributor
Author
|
Could somebody please take a look at this? |
Only conflict was the import block in Kotlin/language.ts: kept master's ESM .js import paths and re-added the PR's type imports (PrimitiveStringTypeKind, TransformedStringTypeKind, StringTypeMapping) in the same style. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Register strict ISO converters on the generated ObjectMapper for OffsetDateTime, LocalDate and OffsetTime via the existing convert() infrastructure instead of requiring jackson-datatype-jsr310: the module's serializers don't round-trip faithfully (OffsetTime pads "23:20:50.52Z" to "23:20:50.520Z"), while the ISO formatters do, and this way generated code needs no extra dependency. Also fix union deserialization when several members are guarded by the same node type: date, time, date-time and enum values are all TextNode, so the previous output had duplicate 'is TextNode ->' branches of which only the first could ever match. Members sharing a guard now parse in a single branch that tries each member in sequence, strictest first (transformed strings, then enums, then plain strings). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The klaxon renderer's matchType calls were missing the transformedStringType matcher the base renderer maps to java.time types, so any schema with date/time formats in a union crashed generation with "Unsupported type date-time in non-exhaustive match". Add the matchers, register Klaxon converters that parse the java.time types from ISO strings and re-serialize them via the ISO formatters (exact round-trip), and give union members that share the 'is String' guard the same sequential-parse treatment as the Jackson renderer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…va.time
With date/time inference now mapping to java.time types, two groups of
misc inputs fail the round-trip comparison: files with non-RFC3339
date-times (space-separated, no offset) that OffsetDateTime.parse
rejects, and files whose fractional seconds have trailing zeros that
the ISO formatters legitimately trim (".000Z" -> "Z"). Skip them for
both Kotlin variants, mirroring what Go already does for the first
group.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Member
|
Update on the CI failures: the fresh run on 379134e confirmed two defects in the feature, and while fixing them we found a third:
We've prepared verified fixes for all three (round-trip byte-identical for both klaxon and jackson locally, fail-case correctly rejected, no regression on non-date output): nikhilunni#1 targets your |
…erence With the default recognizer now requiring RFC 3339 (T separator and timezone offset), space-separated timestamps like "2013-06-15 21:10:28" are inferred as plain strings, so these eight misc fixtures round-trip for both kotlin variants without skips (verified per file; f6a65.json also verified end-to-end with kotlinc). The nine remaining skips are unchanged: their values are RFC 3339-valid but carry trailing-zero fractional seconds (e.g. ".000Z") that java.time does not re-serialize identically. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Kotlin language's stringTypeMapping maps JSON Schema date, time, and date-time formats to java.time types for every framework, but the kotlinx renderer was never taught about them: it emitted @serializable data classes with OffsetDateTime/LocalDate/OffsetTime properties, which don't compile because kotlinx.serialization has no built-in serializers for java.time ("Serializer has not been found for type 'OffsetDateTime'"). Emit custom KSerializer objects for the java.time types that appear in the type graph and register them file-wide with @file:UseSerializers. Like the Jackson and Klaxon converters, they parse with .parse and format with the ISO formatters so values round-trip faithfully. There is no kotlinx fixture in CI, so cover this with a unit test asserting the serializers and file annotation are emitted (and not emitted when no date/time types occur). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # packages/quicktype-core/src/language/Kotlin/KotlinJacksonRenderer.ts # packages/quicktype-core/src/language/Kotlin/KotlinKlaxonRenderer.ts # packages/quicktype-core/src/language/Kotlin/KotlinXRenderer.ts
…erence Merging master brought in the kotlinx fixture coverage from glideapps#2950, whose skip lists were tuned against master, where Kotlin had no date-time support. With this branch's date/time mapping: - Declare the "date-time" feature for KotlinXLanguage. date-time.schema itself stays skipped because its union-array properties hit the kotlinx sealed-class union limitation; the emitted KSerializers are exercised by JSON inputs with inferred date-times instead. - Skip the misc JSON inputs whose date-times carry trailing zeros in the fractional seconds, which java.time doesn't re-serialize identically — the same set already skipped for klaxon and jackson. - Skip date-time-or-string.schema: its string|date-time property was a plain string before and now becomes a union. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
schani
reviewed
Jul 19, 2026
Instead of skipping test inputs whose date-time strings java.time does not re-serialize byte-identically, give Kotlin a DateTimeRecognizer (the existing facility for this, mirroring SwiftDateTimeRecognizer) that refuses to infer date/time types from such strings in the first place. Rejected strings simply stay plain strings. The rules, all verified against java.time's actual parse/format behavior (ISO_LOCAL_DATE / ISO_OFFSET_TIME / ISO_OFFSET_DATE_TIME): - no trailing zeros in fractional seconds (java.time formats the shortest fraction: ".000" disappears, ".500" becomes ".5"), - at most 9 fractional digits (java.time's nanosecond precision; more don't parse), - offset "Z" or a nonzero "±hh:mm" within java.time's ±18:00 range (zero offsets format back as "Z", larger ones don't parse), - uppercase "T" and "Z" (lowercase forms format back in uppercase), - no Feb 29 outside leap years (java.time refuses to parse it). This only affects inference from JSON samples — JSON Schema's "format": "date-time" maps to OffsetDateTime regardless, which is the correct behavior for schema-driven input. The nine date-time-related misc-JSON skips on the Kotlin fixtures are lifted; every date/time-like string in the test inputs that the new recognizer accepts was verified to round-trip byte-identically through java.time (5692 strings checked). 77392.json and b4865.json stay skipped for kotlinx only, for the unrelated top-level-JsonArray reason. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Member
|
Thank you so much, both for your contribution and your patience! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Add support for JSON Schema
format: date-time,format: date, andformat: timein the Kotlin code generator. These formats now generate properjava.time.*types instead ofString.This implementation follows the same pattern as Java's date-time support, using:
OffsetDateTimeforformat: "date-time"LocalDateforformat: "date"OffsetTimeforformat: "time"The feature works across all Kotlin frameworks:
just-types,jackson,klaxon, andkotlinx.Related Issue
Fixes #2460
Motivation and Context
We prefer Kotlin generation to Java generation for nullability propagation, but did not support datetime formatting, as Java does. Plus, saw there was a longstanding issue for this.
Previous Behaviour / Output
For the given JSON schema:
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "eventDate": { "type": "string", "format": "date" }, "eventTime": { "type": "string", "format": "time" }, "plannedDateTime": { "type": "string", "format": "date-time" } } }It would output:
New Behaviour / Output
How Has This Been Tested?
Manual Testing
--framework just-types--framework jackson--framework klaxon--framework kotlinxAutomated Testing
configuration
implementation (commit 1f89a97)