Skip to content

CBOR untaggedNullValueTags configuration option (#2966) - #3074

Open
travishaagen wants to merge 2 commits into
Kotlin:masterfrom
travishaagen:travishaagen.cbor-tag-null
Open

CBOR untaggedNullValueTags configuration option (#2966)#3074
travishaagen wants to merge 2 commits into
Kotlin:masterfrom
travishaagen:travishaagen.cbor-tag-null

Conversation

@travishaagen

@travishaagen travishaagen commented Sep 6, 2025

Copy link
Copy Markdown

Introduces a new CBOR configuration option called untaggedNullValueTags. When enabled, CBOR value-tags will not be serialized for null values, and deserialization will not fail validation. This is allowed by the CBOR spec as mentioned in this issue.

When untaggedNullValueTags=true, the encoding for the provided unit test is https://cbor.me/?bytes=bf6161a0d8226162f6d8386163f66164f6ff where the tags shown below are key-tags,

BF          # map(*)
   61       # text(1)
      61    # "a"
   A0       # map(0)
   D8 22    # tag(34)
      61    # text(1)
         62 # "b"
   F6       # primitive(22)
   D8 38    # tag(56)
      61    # text(1)
         63 # "c"
   F6       # primitive(22)
   61       # text(1)
      64    # "d"
   F6       # primitive(22)
   FF       # primitive(*)

For comparison, when untaggedNullValueTags=false, the encoding is https://cbor.me/?bytes=bf6161cca0d8226162f6d8386163d84ef66164d85accf6ff

BF          # map(*)
   61       # text(1)
      61    # "a"
   CC       # tag(12)
      A0    # map(0)
   D8 22    # tag(34)
      61    # text(1)
         62 # "b"
   F6       # primitive(22)
   D8 38    # tag(56)
      61    # text(1)
         63 # "c"
   D8 4E    # tag(78)
      F6    # primitive(22)
   61       # text(1)
      64    # "d"
   D8 5A    # tag(90)
      CC    # tag(12)
         F6 # primitive(22)
   FF       # primitive(*)

Note however, that Kotlinx Serialization cannot currently deserialize the above anyhow.

This change is needed for a real world use-case, where "untagged null values" are a requirement for value-tags. Thank you!

@travishaagen

Copy link
Copy Markdown
Author

@fzhinkin Hello! Thanks for taking a look. How can I help move this forward?

@fzhinkin fzhinkin added the cbor label Oct 14, 2025
@fzhinkin
fzhinkin self-requested a review May 15, 2026 18:14
@fzhinkin

Copy link
Copy Markdown
Contributor

The change makes sense.

I would only consider a different name for configuration option: all binary flags use a verb in their name, and I don't see why should we make an exception here. Perhaps, skipValueTagsForNulls?

Note that configuration options tend to get a companion-annotation to allow a more fine-grained control over behavior. And while an annotation was not proposed here yet (and I would definitely like to postpone its introduction until it is really necessary), it's worth thinking about how the annotation would look like / what name it would have, to use a coherent option name here. One option here would be just adding an additional boolean parameter to @ValueTags, and then encodeValueTags could be eventually replaced with something like valueTagsEncoding: EncodingStrategy = Always|Never|SkipForNulls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants