Description
When parsing an OpenAPI 3.1 document, schema.getConst() returns null (Java null) when the const keyword is set to a YAML null literal on a scalar field schema. This makes it impossible to distinguish between "no const keyword present" and "const: null is explicitly declared". Both cases produce schema.getConst() == null, so the const: null constraint is silently lost.
By contrast, when null appears as a property value inside an object-typed const (e.g. const: {code: 0, msg: null}), the outer ObjectNode is correctly returned from schema.getConst(), and the inner null is accessible via the node's fields — so object const null properties are not affected.
Affected keyword: const
Affected version: OpenAPI 3.1
Affected Version
io.swagger.parser.v3:swagger-parser-v3:2.1.42
Confirmed by bytecode inspection of OpenAPIDeserializer.class from this jar. The same logic exists in 2.1.32 (also inspected). Likely present since const support was added.
Steps to Reproduce
Spec (YAML):
openapi: "3.1.0"
info:
title: Test
version: "1.0"
paths: {}
components:
schemas:
MySchema:
type: object
properties:
msg:
type: string
const: null # <-- scalar const: null on individual field
code:
type: integer
const: 0
const:
code: 0
msg: null # <-- null inside object const (works correctly)
Test code:
SwaggerParseResult result = new OpenAPIV3Parser().readContents(yaml);
Schema<?> msgSchema = result.getOpenAPI()
.getComponents().getSchemas().get("MySchema")
.getProperties().get("msg");
System.out.println(msgSchema.getConst()); // prints: null (BUG — should be NullNode or distinguishable sentinel)
// No-const field for comparison:
Schema<?> noConst = new Schema<>();
System.out.println(noConst.getConst()); // also prints: null (same result — indistinguishable)
Expected Behavior
schema.getConst() should return a non-null value (e.g. a Jackson NullNode) when const: null is explicitly declared in the spec. This is what happens for all other const value types (const: "hello" → TextNode, const: 42 → IntNode, const: true → BooleanNode, const: {key: val} → ObjectNode).
Consumers of the API need to distinguish "const is not set" from "const is explicitly null". Currently there is no way to make this distinction.
Actual Behavior
schema.getConst() returns Java null for both "no const keyword" and "const: null". The const: null constraint is silently dropped.
Root Cause (Bytecode-Confirmed)
In OpenAPIDeserializer.getAnyType(), the method reads the raw JsonNode for the key. For a YAML null value, Jackson produces a NullNode. The method correctly identifies it at the end of its type-dispatch chain
So schema.setConst(NullNode) is called. The bug is not in the parser placing the value — it is in Schema.getConst() itself. The Schema class has a bindTypes mechanism and a BIND_TYPE_AND_TYPES flag. At some point after deserialization (likely during resolve() or post-processing), Schema transforms or loses the _const field when its value is a NullNode.
Specifically, Schema._const is typed T (generic). When the resolved type T is incompatible with NullNode, or when Jackson's databind serialisation/deserialisation of the schema model converts NullNode to null during a re-serialisation pass (e.g. during $ref resolution), the NullNode is lost and _const becomes Java null.
Environment
- Java version: OpenJDK 21 (IBM Semeru Runtime 21.0.10)
- Build tool: Gradle 8.14
- OS: macOS Darwin 25.3.0 arm64
- swagger-parser-v3:
2.1.42
- swagger-core-jakarta:
2.2.52
- swagger-models-jakarta:
2.2.52
Workaround
Since schema.getConst() is unusable for the null case, a consumer must access the raw parsed JsonNode tree directly via OpenAPIV3Parser.readContents() and traverse the components/schemas/.../properties/.../const path manually, checking JsonNode.isNull() rather than relying on Schema.getConst().
Additional Context
This affects any implementation that relies on schema.getConst() to implement OpenAPI 3.1 const: null validation. JSON Schema (which OAS 3.1 aligns with) explicitly states that const: null is a valid constraint meaning "the value must be null". Silently dropping it means validators cannot enforce null constraints on individual scalar fields.
Object-level const is not affected: const: {key: null} correctly returns an ObjectNode from schema.getConst(), because the outer non-null ObjectNode survives the round-trip. Only the scalar const: null case is broken.
Checklist
Description
When parsing an OpenAPI 3.1 document,
schema.getConst()returnsnull(Java null) when theconstkeyword is set to a YAMLnullliteral on a scalar field schema. This makes it impossible to distinguish between "noconstkeyword present" and "const: nullis explicitly declared". Both cases produceschema.getConst() == null, so theconst: nullconstraint is silently lost.By contrast, when
nullappears as a property value inside an object-typedconst(e.g.const: {code: 0, msg: null}), the outerObjectNodeis correctly returned fromschema.getConst(), and the inner null is accessible via the node's fields — so object const null properties are not affected.Affected keyword:
constAffected version: OpenAPI 3.1
Affected Version
io.swagger.parser.v3:swagger-parser-v3:2.1.42Confirmed by bytecode inspection of
OpenAPIDeserializer.classfrom this jar. The same logic exists in2.1.32(also inspected). Likely present sinceconstsupport was added.Steps to Reproduce
Spec (YAML):
Test code:
Expected Behavior
schema.getConst()should return a non-null value (e.g. a JacksonNullNode) whenconst: nullis explicitly declared in the spec. This is what happens for all otherconstvalue types (const: "hello"→TextNode,const: 42→IntNode,const: true→BooleanNode,const: {key: val}→ObjectNode).Consumers of the API need to distinguish "const is not set" from "const is explicitly null". Currently there is no way to make this distinction.
Actual Behavior
schema.getConst()returns Javanullfor both "no const keyword" and "const: null". Theconst: nullconstraint is silently dropped.Root Cause (Bytecode-Confirmed)
In
OpenAPIDeserializer.getAnyType(), the method reads the rawJsonNodefor the key. For a YAMLnullvalue, Jackson produces aNullNode. The method correctly identifies it at the end of its type-dispatch chainSo
schema.setConst(NullNode)is called. The bug is not in the parser placing the value — it is inSchema.getConst()itself. TheSchemaclass has abindTypesmechanism and aBIND_TYPE_AND_TYPESflag. At some point after deserialization (likely duringresolve()or post-processing),Schematransforms or loses the_constfield when its value is aNullNode.Specifically,
Schema._constis typedT(generic). When the resolved typeTis incompatible withNullNode, or when Jackson's databind serialisation/deserialisation of the schema model convertsNullNodetonullduring a re-serialisation pass (e.g. during$refresolution), theNullNodeis lost and_constbecomes Javanull.Environment
2.1.422.2.522.2.52Workaround
Since
schema.getConst()is unusable for thenullcase, a consumer must access the raw parsedJsonNodetree directly viaOpenAPIV3Parser.readContents()and traverse thecomponents/schemas/.../properties/.../constpath manually, checkingJsonNode.isNull()rather than relying onSchema.getConst().Additional Context
This affects any implementation that relies on
schema.getConst()to implement OpenAPI 3.1const: nullvalidation. JSON Schema (which OAS 3.1 aligns with) explicitly states thatconst: nullis a valid constraint meaning "the value must be null". Silently dropping it means validators cannot enforce null constraints on individual scalar fields.Object-level const is not affected:
const: {key: null}correctly returns anObjectNodefromschema.getConst(), because the outer non-nullObjectNodesurvives the round-trip. Only the scalarconst: nullcase is broken.Checklist