From f9f1a75ba88b29bf79213bb099aa489467c41cb4 Mon Sep 17 00:00:00 2001 From: Yung-Shin Lin Date: Thu, 9 Oct 2025 23:38:13 +0000 Subject: [PATCH 1/6] Address the issue when $ref is an object used in schema, instead of being a real reference. --- .../OpenApiDiff.Core/Logging/ObjectPath.cs | 18 ++++++++++++++++-- package.json | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/openapi-diff/src/core/OpenApiDiff.Core/Logging/ObjectPath.cs b/openapi-diff/src/core/OpenApiDiff.Core/Logging/ObjectPath.cs index b38c83fa..d0b3dc7c 100644 --- a/openapi-diff/src/core/OpenApiDiff.Core/Logging/ObjectPath.cs +++ b/openapi-diff/src/core/OpenApiDiff.Core/Logging/ObjectPath.cs @@ -76,9 +76,23 @@ private static JToken FromObject(JObject o, string name) { return null; } + var @ref = o["$ref"]; - var unrefed = @ref != null ? ParseRef(@ref.Value()).CompletePath(o.Root).Last().token : o; - return unrefed[name]; + + // Handle $ref resolution based on its type + if (@ref != null && @ref.Type == JTokenType.String) + { + // Case 1: $ref is a string reference (e.g., "#/definitions/FieldType") + // Resolve the reference by parsing the path and following it to the target + var unrefed = ParseRef(@ref.Value()).CompletePath(o.Root).Last().token; + return unrefed[name]; + } + else + { + // Case 2: $ref is not a string (e.g., a JSON object defining a schema) + // or $ref doesn't exist - use the current object directly + return o[name]; + } } private static IEnumerable<(JToken token, string name)> CompletePath(IEnumerable> path, JToken token) diff --git a/package.json b/package.json index db788b65..aa539c7d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@azure/oad", - "version": "0.12.2", + "version": "0.12.3", "author": { "name": "Microsoft Corporation", "email": "azsdkteam@microsoft.com", From 9562dfb003fade550920557d9b410b5004fb9e0e Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Mon, 13 Oct 2025 17:00:45 +0000 Subject: [PATCH 2/6] changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8db62b0d..29b5597a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +# 0.12.3 2025-10-13 + +- Only treat "$ref" as reference if value is string + ## 0.12.2 2025-09-22 - bump dependency `js-yaml` from `^3.13.0` to `^4.1.0` From f35120b7bd6220eb882cade65ec2070029a20ce3 Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Mon, 13 Oct 2025 17:31:22 +0000 Subject: [PATCH 3/6] npm i --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 39675859..a3426785 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@azure/oad", - "version": "0.12.2", + "version": "0.12.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@azure/oad", - "version": "0.12.2", + "version": "0.12.3", "license": "MIT", "dependencies": { "@ts-common/fs": "0.2.0", From d3aef24f3252d2747e537c109b03c6889b52a0ac Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Mon, 13 Oct 2025 18:28:40 +0000 Subject: [PATCH 4/6] Add test PropertyNamedRefTypeChanged --- .../Resource/Swagger/new/type_changed_02.json | 48 +++++++++++++++++++ .../Resource/Swagger/old/type_changed_02.json | 48 +++++++++++++++++++ .../SwaggerModelerCompareTests.cs | 15 ++++++ 3 files changed, 111 insertions(+) create mode 100644 openapi-diff/src/modeler/AutoRest.Swagger.Tests/Resource/Swagger/new/type_changed_02.json create mode 100644 openapi-diff/src/modeler/AutoRest.Swagger.Tests/Resource/Swagger/old/type_changed_02.json diff --git a/openapi-diff/src/modeler/AutoRest.Swagger.Tests/Resource/Swagger/new/type_changed_02.json b/openapi-diff/src/modeler/AutoRest.Swagger.Tests/Resource/Swagger/new/type_changed_02.json new file mode 100644 index 00000000..b9565036 --- /dev/null +++ b/openapi-diff/src/modeler/AutoRest.Swagger.Tests/Resource/Swagger/new/type_changed_02.json @@ -0,0 +1,48 @@ +{ + "swagger": 2.0, + "info": { + "title": "type_changed", + "version": "1.0" + }, + "host": "localhost:8000", + "schemes": [ "http", "https" ], + "consumes": [ "text/plain", "text/json" ], + "produces": [ "text/plain" ], + "paths": { + "/api/Parameters": { + "put": { + "tag": [ "Parameters" ], + "operationId": "Parameters_Put", + "produces": [ + "text/plain" + ], + "parameters": [ + { + "name": "database", + "in": "body", + "required": true, + "type": "object", + "schema": { "$ref": "#/definitions/Database" } + } + ] + } + } + }, + "definitions": { + "Database": { + "properties": { + "$ref": { + "type": "integer", + "readOnly": true, + "description": "Property named '$ref'. Unusual but valid." + }, + "b": { + "type": "integer", + "readOnly": true, + "default": 0, + "description": "This property shows the number of databases returned." + } + } + } + } +} diff --git a/openapi-diff/src/modeler/AutoRest.Swagger.Tests/Resource/Swagger/old/type_changed_02.json b/openapi-diff/src/modeler/AutoRest.Swagger.Tests/Resource/Swagger/old/type_changed_02.json new file mode 100644 index 00000000..c072fd1c --- /dev/null +++ b/openapi-diff/src/modeler/AutoRest.Swagger.Tests/Resource/Swagger/old/type_changed_02.json @@ -0,0 +1,48 @@ +{ + "swagger": 2.0, + "info": { + "title": "type_changed", + "version": "1.0" + }, + "host": "localhost:8000", + "schemes": [ "http", "https" ], + "consumes": [ "text/plain", "text/json" ], + "produces": [ "text/plain" ], + "paths": { + "/api/Parameters": { + "put": { + "tag": [ "Parameters" ], + "operationId": "Parameters_Put", + "produces": [ + "text/plain" + ], + "parameters": [ + { + "name": "database", + "in": "body", + "required": true, + "type": "object", + "schema": { "$ref": "#/definitions/Database" } + } + ] + } + } + }, + "definitions": { + "Database": { + "properties": { + "$ref": { + "type": "string", + "readOnly": true, + "description": "Property named '$ref'. Unusual but valid." + }, + "b": { + "type": "integer", + "readOnly": true, + "default": 0, + "description": "This property shows the number of databases returned." + } + } + } + } +} diff --git a/openapi-diff/src/modeler/AutoRest.Swagger.Tests/SwaggerModelerCompareTests.cs b/openapi-diff/src/modeler/AutoRest.Swagger.Tests/SwaggerModelerCompareTests.cs index 37620bf2..56b36893 100644 --- a/openapi-diff/src/modeler/AutoRest.Swagger.Tests/SwaggerModelerCompareTests.cs +++ b/openapi-diff/src/modeler/AutoRest.Swagger.Tests/SwaggerModelerCompareTests.cs @@ -165,6 +165,21 @@ public void TypeObjectChanged() Assert.Equal("new/type_changed_01.json#/definitions/Database/properties/a", error.NewJsonRef); } + /// + /// Verifies that if you change the type of a schema property named "$ref", it's caught. + /// + [Fact] + public void PropertyNamedRefTypeChanged() + { + var messages = CompareSwagger("type_changed_02.json").ToArray(); + var missing = messages.Where(m => m.Id == ComparisonMessages.TypeChanged.Id); + Assert.NotEmpty(missing); + var error = missing.Where(err => err.NewJsonRef.StartsWith("new/type_changed_02.json#/definitions/")).FirstOrDefault(); + Assert.NotNull(error); + Assert.Equal(Category.Error, error.Severity); + Assert.Equal("new/type_changed_02.json#/definitions/Database/properties/$ref", error.NewJsonRef); + } + /// /// Verifies that if you change the default value of a schema, it's caught. /// From df07e6c568e3a8b4cba0ce6aff8bd6a468ada895 Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Mon, 13 Oct 2025 18:30:17 +0000 Subject: [PATCH 5/6] comment --- .../AutoRest.Swagger.Tests/SwaggerModelerCompareTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi-diff/src/modeler/AutoRest.Swagger.Tests/SwaggerModelerCompareTests.cs b/openapi-diff/src/modeler/AutoRest.Swagger.Tests/SwaggerModelerCompareTests.cs index 56b36893..a00bafe5 100644 --- a/openapi-diff/src/modeler/AutoRest.Swagger.Tests/SwaggerModelerCompareTests.cs +++ b/openapi-diff/src/modeler/AutoRest.Swagger.Tests/SwaggerModelerCompareTests.cs @@ -166,7 +166,7 @@ public void TypeObjectChanged() } /// - /// Verifies that if you change the type of a schema property named "$ref", it's caught. + /// Verifies that if you change the type of a schema property named "$ref" (unusual but valid), it's caught. /// [Fact] public void PropertyNamedRefTypeChanged() From 76ccd8f3220863bb2aeb34fdc93a6bee67f2ad31 Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Mon, 13 Oct 2025 18:32:49 +0000 Subject: [PATCH 6/6] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29b5597a..161061bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 0.12.3 2025-10-13 -- Only treat "$ref" as reference if value is string +- Fix crash in logging when property named "$ref" ## 0.12.2 2025-09-22