[Phase 3b] MSSQL JSON - return json as string on read + OpenAPI/GraphQL tests - #3738
Open
souvikghosh04 wants to merge 4 commits into
Open
[Phase 3b] MSSQL JSON - return json as string on read + OpenAPI/GraphQL tests#3738souvikghosh04 wants to merge 4 commits into
souvikghosh04 wants to merge 4 commits into
Conversation
… 3b) Proves the 'JSON is treated as a normal string' contract at the schema-discovery layer, complementing the merged REST round-trip tests (#3720). - JsonTypeSchemaTests (T008): the profiles.metadata json column is exposed in the OpenAPI document as type:string, nullable, with no bespoke format. - MsSqlGraphQLJsonSchemaTests (T009): GraphQL introspection reports Profile.metadata as the built-in nullable String scalar (no custom JSON scalar). MCP describe_entities (T010) is intentionally omitted: describe_entities projects only config field name/description, not DB column data types, so there is no JSON-specific behavior to assert there.
souvikghosh04
marked this pull request as ready for review
July 28, 2026 08:07
souvikghosh04
requested review from
Alekhya-Polavarapu,
JerryNixon,
RubenCerna2079,
aaronburtle,
anushakolan,
rusamant,
sourabh1007,
stuartpa and
vadeveka
as code owners
July 28, 2026 08:07
Contributor
There was a problem hiding this comment.
Pull request overview
Adds schema-discovery test coverage for SQL Server 2025 native json columns to ensure DAB continues to expose them exactly like normal nullable string fields at the OpenAPI and GraphQL layers (no bespoke JSON scalar/format), aligning with the Phase 3b goals.
Changes:
- Adds an OpenAPI component-schema assertion that
profiles.metadataistype: string,nullable: true, with noformat. - Adds a GraphQL introspection assertion that
Profile.metadatais the built-in nullableStringscalar (no custom JSON scalar).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs | New GraphQL introspection test validating json columns map to built-in nullable String. |
| src/Service.Tests/OpenApiDocumentor/JsonTypeSchemaTests.cs | New OpenAPI generation test validating json columns are described as nullable string with no format. |
2 tasks
…ocumentor) CI failure: JsonColumn Nullable assertion failed. DAB's OpenApiDocumentor builds each column property schema with only Type/Format/Description/Items and never sets Nullable for any column (nullability is expressed via request-body required lists, not the property schema). The assertion was wrong and not JSON-specific. Keep the meaningful 'nothing special' assertions: type==string and no format. Renamed the test to JsonColumn_IsDescribedAsStringWithoutFormat.
aaronburtle
reviewed
Jul 29, 2026
aaronburtle
reviewed
Jul 29, 2026
aaronburtle
reviewed
Jul 29, 2026
…review Per #2768, a JSON column must be treated as a string for input AND output. But the MSSQL read path (FOR JSON PATH) was inlining a native json column as a nested JSON object, so REST returned an object and a GraphQL read of the String-typed field threw a GraphQLMapping error (String leaf resolver calls JsonElement.GetString(), which fails on an object). Engine: MsSqlQueryBuilder.WrappedColumns now casts a native json column (SqlDbType.Json) to NVARCHAR(MAX) so FOR JSON PATH emits it as an escaped JSON string. Mutations already return json as a string via the tabular OUTPUT clause, so no change was needed there. Regular nvarchar columns are untouched. Tests (addresses aaronburtle review on #3738): - Flip MsSqlRestJsonTypesTests back to the string contract (ParseMetadata/GetJsonTypeList assert JsonValueKind.String). - Add GraphQL end-to-end read (profile_by_pk metadata) asserting the payload returns as a JSON string - guards against introspection passing while a real read throws. - OpenAPI test now asserts metadata is type:string with no format in the response AND the POST/PUT-PATCH request-body components (Profile_NoAutoPK/Profile_NoPK).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Part of MSSQL native
JSONsupport (#2768). Started as Phase 3b schema-discovery tests, but review (thanks @aaronburtle) surfaced a real product inconsistency that this PR now also fixes.The problem: #2768 requires a
JSONcolumn to be treated as a normalstringfor input and output. But the MSSQL read path (FOR JSON PATH) was inlining a nativejsoncolumn as a nested JSON object. Consequences:"metadata": {"role":"admin"}(object) instead of"metadata": "{\"role\":\"admin\"}"(string).String-typed field threw aGraphQLMappingerror — theStringleaf resolver callsJsonElement.GetString(), which fails on an object. So schema introspection could pass whileprofile_by_pk(id:1){ metadata }failed at runtime.string, contradicting the object runtime — generated clients would mis-model the field.What
Engine fix (
MsSqlQueryBuilder): the read path now casts a nativejsoncolumn (SqlDbType.Json) toNVARCHAR(MAX)inWrappedColumns, soFOR JSON PATHemits it as an escaped JSON string rather than inlining it as an object. This is the single choke point for REST and GraphQL reads. Regularnvarcharcolumns are untouched. Mutations already returnjsonas a string via the tabularOUTPUTclause, so no change was needed there.Tests:
JsonTypeSchemaTestsmetadataistype: stringwith noformatin the response and both request-body schemas (Profile_NoAutoPKfor POST,Profile_NoPKfor PUT/PATCH)MsSqlGraphQLJsonSchemaTestsProfile.metadatais the built-inStringscalar (no custom JSON scalar)MsSqlGraphQLJsonSchemaTestsprofile_by_pk(id:1){ metadata }returns the payload as a JSON string — guards against introspection passing while a real read throwsMsSqlRestJsonTypesTests(updated)metadatais returned as a JSON string (ParseMetadata/GetJsonTypeListassertJsonValueKind.String)Intentionally omitted
describe_entities(T010): it projects only the config fieldname/description, not DB column data types, so there is no JSON-specific behavior to assert.Notes
json); CI already runs SQL 2025.Delivery plan