Skip to content

feat(ack): import JSON Schema pattern and propertyNames - #158

Merged
leoafarias merged 5 commits into
mainfrom
feat/json-schema-import-pattern-property-names
Sep 22, 2026
Merged

leoafarias merged 5 commits into
mainfrom
feat/json-schema-import-pattern-property-names

Conversation

@leoafarias

@leoafarias leoafarias commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Ack.fromJsonSchema() now compiles the pattern and propertyNames keywords.

  • pattern — stored as its raw source string and applied to strings only, as an unanchored ECMA-262 search (JSON Schema §6.3.3, the same semantics PatternConstraint.regex already uses). Rejected at import time when it is not a valid regular expression string, matching the existing "rejects malformed supported keywords" contract.
  • propertyNames — validates every key of an object instance against its subschema. Type-specific as usual: skipped, never failed, for non-objects.

The implementation stays within the existing compiler and validator. No new public API or fromJsonSchema option, and no change to render.

Why

Ack already emitted pattern from Ack.string().matches(...), but could not read it back: Ack.fromJsonSchema(schema.toJsonSchema()) threw on that native output. propertyNames is a standard keyword in external schemas that the importer also lacked. Native Ack.map(valueSchema) exports additionalProperties; it does not emit propertyNames. This change closes the native pattern round-trip hole and adds strict import support for propertyNames.

The concrete driver: mix_protocol publishes Draft-7 schemas exported from Ack and validates them with an independent Node/Ajv job. All four of its suites failed to re-import on pattern. With this change all 284 checked-in fixture documents import and agree with Ajv on every accept/reject verdict in that set, 0 mismatches. This is fixture-specific: default Ajv enables the Unicode u flag, while Ack's default Dart RegExp does not. For example, `^.### Description

Ack.fromJsonSchema() now compiles the pattern and propertyNames keywords.

  • pattern — stored as its raw source string and applied to strings only, as an unanchored ECMA-262 search (JSON Schema §6.3.3, the same semantics PatternConstraint.regex already uses). Rejected at import time when it is not a valid regular expression string, matching the existing "rejects malformed supported keywords" contract.
  • propertyNames — validates every key of an object instance against its subschema. Type-specific as usual: skipped, never failed, for non-objects.

The implementation stays within the existing compiler and validator. No new public API or fromJsonSchema option, and no change to render.

Why

Ack already emitted pattern from Ack.string().matches(...), but could not read it back: Ack.fromJsonSchema(schema.toJsonSchema()) threw on that native output. propertyNames is a standard keyword in external schemas that the importer also lacked. Native Ack.map(valueSchema) exports additionalProperties; it does not emit propertyNames. This change closes the native pattern round-trip hole and adds strict import support for propertyNames.

The concrete driver: mix_protocol publishes Draft-7 schemas exported from Ack and validates them with an independent Node/Ajv job. All four of its suites failed to re-import on pattern. has a different verdict for 😀. Test patterns in both validators when cross-runtime agreement is required.

Export

Unchanged, deliberately. _ImportedNode.render already emits keywords verbatim and every children entry as a $ref, so pattern round-trips as its raw string and propertyNames as a $ref. Draft-7 supports both, so re-import of the export is lossless with zero export code.

Tests

  • Conformance fixtures grow from 178 groups / 600 cases to 186 / 631, appended from the pinned commit 80c87e8fca8b207a7a7ae944b875f0fcf889f46a of the upstream suite, keeping the existing conventions. json_schema_import_conformance_test.dart needed no edit — it already asserts parse, encode, and re-import-of-export for every case.
    • One upstream group is deliberately excluded: pattern with Unicode property escape requires unicode mode. Dart's default RegExp does not match \p{Letter} the way that group expects, so it is represented by absence rather than a silent skip, per the fixture README's rule.
  • Three unit tests: malformed-pattern rejection, behaviour + export shape + re-import, and the propertyNames error path and offending key value.

Versioning

None. version: stays at 1.6.1 and the changelog entry sits under ## Unreleased, per PUBLISHING.md — the coordinated release PR picks the number and bumps all six packages together.

dart scripts/api_check.dart ack v1.6.1 reports no public API changes.

Verification

On commit a87ad707, all PR checks passed:

  • CI: formatting, workspace analysis and tests, and Chrome JSON Schema import tests.
  • Documentation.
  • Release preflight: API compatibility, minimum SDK checks, generation, publish dry run, and Draft-7 validation.

Ack.fromJsonSchema() now compiles the `pattern` and `propertyNames`
keywords. `pattern` is stored as its raw source string and applied to
strings only as an unanchored ECMA-262 search, and is rejected at import
time when it is not a valid regular expression string. `propertyNames`
validates every key of an object instance against its subschema.

Ack already emitted both keywords from `Ack.string().matches(...)` and
from keyed maps, so until now it could not re-import its own export. The
generic Draft-7 renderer needs no change: `pattern` round-trips as its raw
string and `propertyNames` as a `$ref`, so the export path is untouched.

The pinned upstream conformance selection grows to 186 groups / 631
instance cases. The one upstream `pattern` group requiring unicode mode
stays out, since Dart's default RegExp does not match it.

Also documents that the dialect gate only inspects the declared `$schema`
string, and names the two Draft-7 shapes that do not survive the swap.

No public API change: `dart scripts/api_check.dart ack v1.6.1` reports no
changes. Versioning is left to the coordinated release PR.
The excluded upstream group is a semantic deviation, not an unsupported
keyword: its schema imports cleanly and only the match result differs.
Recording it in the fixture README and the guide keeps it from reading as
a silent skip, which that README forbids.
@leoafarias
leoafarias merged commit 931db33 into main Sep 22, 2026
8 checks passed
@leoafarias
leoafarias deleted the feat/json-schema-import-pattern-property-names branch September 22, 2026 23:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant