In case people don't understand why Jackson 3 has the breaking change.
It fixes older anomalies. AI description (repeats some of what
Daniel/Scott said earlier):

====
Current master (Jackson 2.22.4 with SnakeYAML). I ran this against the
groovy-yaml jar from master:

// Input
country_codes: [ge, fr, no]
flags: [yes, off, True, NULL, ~, 0x1F]

// After parsing
country_codes: [ge, fr, false]           -> String, String, Boolean
flags: [true, false, true, null, null, 31]

That's the "Norway problem". Jackson 2's YAML backend is SnakeYAML,
which follows YAML 1.1. Under 1.1, yes/no/on/off in any case are
booleans, ~ and NULL are null, and 0x1F is an integer. The JSON round
trip I described earlier keeps whatever SnakeYAML decided.

PR #2949 (GROOVY-12433, open, moves groovy-yaml/toml/csv to Jackson
3.2.4). Jackson 3's YAML parser is built on SnakeYAML Engine, which
follows YAML 1.2. It resolves plain scalars with the JSON schema, and
that is fixed inside the parser, so there's no setting to change it.
Only lowercase true, false, null and plain decimal numbers get a type.
So:

- no → 'no' (Norway survives), and the same goes for yes/on/off.
- True, FALSE, Null, NULL and ~ stay strings too. This is stricter
than the YAML 1.2 core schema most parsers use, where True/Null/~
still get a type.
- 0x1F, 017 and 1_000 stay strings.
- .inf, -.inf and .nan now parse. The typed API gives Double values;
YamlSlurper.parseText gives the strings 'Infinity', '-Infinity' and
'NaN', because of the JSON round trip.

The catch the PR calls out: a non-empty String is truthy in Groovy. So
enabled: off read with parseText used to be false and will now test as
true, with no error. The typed parseAs/parseTextAs path does reject
off for a boolean property. The PR lists this under breaking changes
in COMPATIBILITY.md, pins the behaviour in YamlScalarResolutionTest,
and adds a YAML-guide recipe that loads YAML 1.1 documents with
SnakeYAML directly.

So the PR doesn't target the Norway problem. It fixes it as a
by-product of the Jackson 3 move, and in exchange any existing config
that relies on yes/no/on/off changes meaning without any error. That
silent truthiness flip is the thing to weigh when reviewing it for
Groovy 7.
====

The current suggestion is that if you need 'off' going to a boolean
not a String, use SnakeYAML directly.
There is also a gotcha for typed Xml Parsing and old less common
Jackson 2 annotations but that is also documented.

Cheers,
Paul.

On Fri, Oct 30, 2026 at 6:19 AM Scott Murphy Heiberg
<[email protected]> wrote:
>
> Hi Jochen, Daniel,
>
> Thanks both.
>
> Jochen, you're right that this lands on neither 1.1 nor 1.2 core. The docs 
> now say exactly that: the YAML guide and a new Groovy 7 section in 
> COMPATIBILITY.md describe the resolver as the JSON schema, stricter than the 
> YAML 1.2 core schema, and list the values that change. On custom type 
> transformations, Jackson 3's YAML parser doesn't expose a hook for that. Paul 
> tried passing SnakeYAML Engine's CoreSchema through the factory's load 
> settings, and it made no difference. Where types matter, the typed 
> parseAs/parseTextAs path is the stricter option: it rejects "off" for a 
> boolean property instead of handing back a truthy string.
>
> On your cases:
>
> - GitLab CI: groovy-yaml doesn't resolve aliases or apply merge keys, before 
> or after this change (GROOVY-12358). The guide's SnakeYAML recipe does both, 
> so that's the route for CI files today. Includes and !reference are GitLab's 
> own, so they'd need handling on top either way.
> - Simple config files written to the newer schemas: no change, apart from 
> 0x1F, 017 and 1_000, and Null/True and the like, which the core schema would 
> still type.
> - Agentic AI output: the strict resolution helps here, and typed parsing also 
> rejects unknown properties.
> - Skill files with front matter: extracting the block and passing it to 
> parseText works as before.
>
> We aren't taking on a YAML 1.1 parser. The SnakeYAML recipe is documentation 
> only and adds no Groovy dependency.
>
> Daniel, thanks for reviewing. The migration notes you asked for are in #2949 
> now: a COMPATIBILITY.md section (b6d43bc) listing each break with who is 
> affected and what to do, plus the breaking-changes list in the PR description.
>
> Cheers,
> Scott
>
> On 2026-10-28 16:10 UTC Daniel Sun wrote:
> > Hi Scott, Jochen,
> >
> > Thanks for raising this on the list rather than letting it land quietly 
> > with the Jackson 3 move.
> >
> > I agree the breakage around unquoted YAML 1.1-style scalars 
> > (`yes`/`no`/`on`/`off`, mixed-case booleans, `~`, octal/hex) needs to stay 
> > explicit for Groovy 7. Documenting it as a breaking change, pinning it with 
> > a test, and pointing at SnakeYAML for documents that still need the older 
> > typing looks like the right packaging for the default Jackson-based path.
> >
> > Jochen's point about not really landing on YAML 1.2 core either is fair; we 
> > should keep the release notes honest about what the resolver does and does 
> > not do. I am fine shipping with the documented behaviour if the guide and 
> > migration notes stay clear, and I am happy to review #2949 / GROOVY-12433 
> > with that in mind.
> >
> > Cheers,
> > Daniel Sun
> >

Reply via email to