Skip to content

[minor] Keep scalar types and nulls through a frontmatter round trip - #174

Merged
matt-edmondson merged 3 commits into
mainfrom
fix/137-preserve-scalar-types
Sep 30, 2026
Merged

matt-edmondson merged 3 commits into
mainfrom
fix/137-preserve-scalar-types

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #137

What changed

This follows all three parts of the issue's suggested fix:

  1. Read. The deserializer uses WithAttemptingUnquotedStringTypeDeserialization(). Plain scalars now come back as bool, integer, float or null, and quoted scalars stay strings.
  2. Write. The serializer uses WithQuotingNecessaryStrings(), so a string such as "true" or "007" is written quoted. A real draft: false is still written as an unquoted boolean.
  3. Nulls. ConvertValue keeps a null as a null instead of turning it into string.Empty. DefaultValuesHandling.Preserve then writes it back as a null.

Keeping nulls needed a change in PropertyMerger.MergePropertyGroup. It used to drop a group whose first value was null, and to throw when a mixed-type group contained a null. Both cases now copy every key through with its own value.

Behaviour change

ExtractFrontmatter (and the other paths that read frontmatter) now return typed values for plain scalars, for example bool, a number, or null. Before, every scalar came back as a string. A caller that cast values to string will see different types, so this is tagged [minor]. PropertyMergerTests.CombineFrontmatter_SingleBlockWithRepeatedListItems_RoundTripsTheLists asserted the old behaviour (scores: [1, 1, 2] read back as strings), so I updated it to compare numbers.

Tests

Frontmatter.Test/ScalarTypeRoundTripTests.cs:

  • The issue's input runs through CombineFrontmatter under None and Conservative. The output is re-read with a typed YamlDotNet reader. The quoted look-alikes stay strings, empty stays null, draft stays an unquoted false, and count stays numeric.
  • AddFrontmatter quotes "true" and "007".
  • ExtractFrontmatter tells a plain false apart from a quoted "false".

Results:

  • With the fix: 217/217 pass (dotnet test)
  • With YamlSerializer.cs and PropertyMerger.cs reverted: all 4 new tests fail

🤖 Generated with Claude Code

https://claude.ai/code/session_01AFCuHRLN6NWMQ4DJNZApHa


Generated by Claude Code

Every scalar was read back as a string and written bare, so quoted
"true", "1.0", "01234" and "null" came back as a bool, number or
null, and an empty value became ''. The reader now keeps plain scalars
typed (bool, integer, float, null) while quoted scalars stay strings,
the writer quotes strings that would otherwise read as another type, and
a null is kept as a null. PropertyMerger keeps a null-valued key instead
of dropping it or throwing.

ExtractFrontmatter now returns typed values for plain scalars rather
than strings, hence [minor].

Fixes #137

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFCuHRLN6NWMQ4DJNZApHa
Comment thread Frontmatter.Test/ScalarTypeRoundTripTests.cs Fixed
@sonarqubecloud

Copy link
Copy Markdown

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.

Round-tripping strips quotes, so "true", "1.0", "007" and "null" come back as bool/number/null, and empty values become ''

2 participants