Skip to content

Default ObjectMapper now serializes numeric schema keywords as strings since 5.0.0 #576

Description

@cschwich

Description

Starting with version 5.0.0, jsonschema-generator switched to Jackson 3 and introduced a change in how the default ObjectMapper is created in SchemaGeneratorConfigBuilder. This unintentionally introduced a regression: numeric JSON Schema keywords (e.g., minLength, minItems, maxProperties, etc.) are now serialized as strings instead of numbers when the default mapper is used (which is the case in the Maven plugin).

Background

In versions < 5.0.0, the method createDefaultObjectMapper() looked like this:

private static ObjectMapper createDefaultObjectMapper() {
    ObjectMapper mapper = new ObjectMapper()
            // since version 4.32.0; pretty print by default (can be overridden by supplying explicit mapper)
            .enable(SerializationFeature.INDENT_OUTPUT);
    mapper.getSerializationConfig()
            // since version 4.21.0
            .with(JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS);
    // since version 4.25.0; as the above doesn't always work
    mapper.setNodeFactory(JsonNodeFactory.withExactBigDecimals(true));

    return mapper;
}

The call to:

mapper.getSerializationConfig().with(JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS);

had no effect, because with(...) returns a new SerializationConfig instance which is not applied back to the ObjectMapper.
Thus, although the feature was declared, numerical values were still serialized correctly as numbers.

Change in 5.0.0

Since 5.0.0, the method was rewritten using JsonMapper.builder():

private static ObjectMapper createDefaultObjectMapper() {
    return JsonMapper.builder()
            // since version 4.32.0; pretty print by default (can be overridden by supplying explicit mapper)
            .enable(SerializationFeature.INDENT_OUTPUT)
            // since version 4.21.0
            .enable(JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS)
            // since version 4.25.0; as the above doesn't always work
            .enable(JsonNodeFeature.STRIP_TRAILING_BIGDECIMAL_ZEROES)
            .build();
}

This time, WRITE_NUMBERS_AS_STRINGS is actually applied to the mapper, because the builder enforces it during construction.

As a result, all numbers — including JSON Schema keywords — are serialized as strings, for example:

{
  "type": "string",
  "minLength": "3"
}

instead of:

{
  "type": "string",
  "minLength": 3
}

This violates the JSON Schema specification and breaks downstream tooling.

Impact

  • The Maven plugin is directly affected because it uses the default mapper.
  • JSON Schema validators, editors, and code generators may reject or misinterpret schemas.
  • This is a behavior regression compared to version 4.x, where numbers were always written as numbers.

Expected behavior

Numeric JSON Schema keywords should be serialized as numbers, consistent with:

  • JSON Schema specification
  • Behavior of jsonschema-generator < 5.0.0
  • Jackson's default behavior

The default mapper should not turn schema metadata fields into strings.

Possible solutions

  1. Remove JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS from the default mapper
    → safest choice, because the feature was not actually effective in previous versions.

  2. Apply number-to-string conversion only to actual instance values
    → likely impractical, since schema serialization uses a single mapper.

  3. Keep the behavior but document the breaking change
    → does not help Maven plugin users unless they explicitly override the mapper.

  4. Retain strict BigDecimal handling (withExactBigDecimals(true)) without enabling global number-to-string conversion
    → closest to the original intention.

Suggested fix

Remove:

.enable(JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS)

from the default mapper in 5.x, because the feature was never effectively active in earlier versions and now causes incorrect JSON Schema output.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions