Skip to content

A null default is incorrectly deserialized as JsonValue of kind string with value of "null" from YAML and there is no way to distinguish between an undefined default value and a null default value. #2510

Description

Describe the bug
When deserializing default value from a YAML document and that value is null it is converted to a JsonValue of kind string with the value of "null" making it ambiguous. In actuality it should result in a null JsonNode. Furthermore, there is no way to distinguish between an unset default value and a default value of null since JsonNode cannot represent a JSON null value beyond being null itself.

OpenApi File To Reproduce
https://api.ynab.com/papi/open_api_spec.yaml

Expected behavior
Default would return null instead of a JsonValue of kind string when deserializing from YAML and an additional property should be added such as DefaultIsNull. Alternatively, the type for the Default property should perhaps be changed to JsonElement with correct type deserialization.

Screenshots/Code Snippets
Currently have this workaround which tries to guess whether Default should be considered a null value or a string of "null".

var valueKind = property.Default.GetValueKind();
if (valueKind is JsonValueKind.String
    && property.Default.GetValue<string>() == "null"
    && property.Type is not null
    && (!property.Type.Value.HasFlag(JsonSchemaType.String) || property.Type.Value.HasFlag(JsonSchemaType.Null)))
    valueKind = JsonValueKind.Null;

Activity

  1. changed the title [-]A `null` `default` is incorrectly deserialized as JsonValue with kind string and value "null" from YAML and there is no way to distinguish between an "undefined" default value and a "null" default value.[/-] [+]A `null` `default` is incorrectly deserialized as `JsonValue` of kind string with value of "null" from YAML and there is no way to distinguish between an `undefined` `default` value and a `null` `default` value.[/+] on Sep 19, 2025
  2. added a commit that references this issue on Oct 22, 2025
    231f562
  3. added this to the v3 milestone on Oct 22, 2025
  4. baywet commented on Oct 22, 2025

    @baywet
    Member

    Hi Jonathan Porter (@jkporter)
    Thank you for using the SDK and for reaching out.

    I've implemented a fix for the YAML deserialization in #2559.

    For the "assigning null from the object model, and wanting serialized null values" problem, it's going to be longer to fix because of a design issue, which would require a source breaking change.
    Essentially, system.text.json DOES NOT provide a JsonNode/Value for "null", and they probably never will add one as they want a single primitive for null (the other one being dotnet null). dotnet/runtime#68128
    Because of that, and the fact that default, example, and value use JsonNode, it's semantically impossible for you as a consumer to "tell the difference" between "the value was never assigned, or reset" and "the value should be null in the serialized representation".

    The proper solution to that, which is source breaking and will require a new major version, would be to:

    1. Define a new type e.g. "JsonNodeWrapper" with either a flag for null values, or a subtype.
    2. Update all properties that use JsonNode in the object model to use that new type.
    3. Implement implicit conversion from JsonNode to that type (so the API for consumers stays roughly the same)
    4. Update the deserialization code to special case reading null.
  5. C0nquistadore commented on Oct 22, 2025

    @C0nquistadore

    This is really unfortunate. To be honest, this is already a breaking change, because it worked perfectly fine in v1, at least the scenario I described in #2554. So this means, this blocks us from upgrading from v1 to v2 and instead we have to wait for the next major version, whenever that will be.

  6. baywet commented on Oct 23, 2025

    @baywet
    Member

    I did think about this problem again, and using a sentinel value seems to address it without causing a breaking change. See #2563

  7. modified the milestones: v3, 2.1 on Oct 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

type:breaking-changeAn issue that will result in dependent client projects failing.

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions