Skip to content

Commit 07237af

Browse files
committed
Implement serialization and deserialization logic for unrecognized JSON schema keywords
1 parent 47bf1eb commit 07237af

File tree

4 files changed

+51
-2
lines changed

4 files changed

+51
-2
lines changed

src/Microsoft.OpenApi/Models/OpenApiConstants.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,11 @@ public static class OpenApiConstants
480480
/// </summary>
481481
public const string Properties = "properties";
482482

483+
/// <summary>
484+
/// Field: UnrecognizedKeywords
485+
/// </summary>
486+
public const string UnrecognizedKeywords = "unrecognizedKeywords";
487+
483488
/// <summary>
484489
/// Field: Pattern Properties
485490
/// </summary>

src/Microsoft.OpenApi/Models/OpenApiSchema.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

44
using System;
@@ -327,6 +327,11 @@ public virtual IList<JsonNode> Examples
327327
/// </summary>
328328
public virtual IDictionary<string, IOpenApiExtension> Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
329329

330+
/// <summary>
331+
/// This object stores any unrecognized keywords found in the schema.
332+
/// </summary>
333+
public virtual IDictionary<string, JsonNode> UnrecognizedKeywords { get; set; } = new Dictionary<string, JsonNode>();
334+
330335
/// <summary>
331336
/// Indicates object is a placeholder reference to an actual object and does not contain valid data.
332337
/// </summary>
@@ -403,6 +408,7 @@ public OpenApiSchema(OpenApiSchema schema)
403408
UnresolvedReference = schema?.UnresolvedReference ?? UnresolvedReference;
404409
Reference = schema?.Reference != null ? new(schema?.Reference) : null;
405410
Annotations = schema?.Annotations != null ? new Dictionary<string, object>(schema?.Annotations) : null;
411+
UnrecognizedKeywords = schema?.UnrecognizedKeywords != null ? new Dictionary<string, JsonNode>(schema?.UnrecognizedKeywords) : null;
406412
}
407413

408414
/// <summary>
@@ -554,6 +560,12 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
554560
// extensions
555561
writer.WriteExtensions(Extensions, version);
556562

563+
// Unrecognized keywords
564+
if (UnrecognizedKeywords.Any())
565+
{
566+
writer.WriteOptionalMap(OpenApiConstants.UnrecognizedProperties, UnrecognizedKeywords, (w,s) => w.WriteAny(s));
567+
}
568+
557569
writer.WriteEndObject();
558570
}
559571

src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
using Microsoft.OpenApi.Reader.ParseNodes;
88
using System.Collections.Generic;
99
using System.Globalization;
10+
using System.Linq;
11+
using System.Text.Json.Nodes;
1012

1113
namespace Microsoft.OpenApi.Reader.V31
1214
{
@@ -254,7 +256,17 @@ public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocum
254256

255257
foreach (var propertyNode in mapNode)
256258
{
257-
propertyNode.ParseField(schema, _openApiSchemaFixedFields, _openApiSchemaPatternFields);
259+
bool isRecognized = _openApiSchemaFixedFields.ContainsKey(propertyNode.Name) ||
260+
_openApiSchemaPatternFields.Any(p => p.Key(propertyNode.Name));
261+
262+
if (isRecognized)
263+
{
264+
propertyNode.ParseField(schema, _openApiSchemaFixedFields, _openApiSchemaPatternFields);
265+
}
266+
else
267+
{
268+
schema.UnrecognizedKeywords[propertyNode.Name] = propertyNode.JsonNode;
269+
}
258270
}
259271

260272
if (schema.Extensions.ContainsKey(OpenApiConstants.NullableExtension))

src/Microsoft.OpenApi/Writers/OpenApiWriterExtensions.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections;
66
using System.Collections.Generic;
77
using System.Linq;
8+
using System.Text.Json.Nodes;
89
using Microsoft.OpenApi.Interfaces;
910

1011
namespace Microsoft.OpenApi.Writers
@@ -253,6 +254,25 @@ public static void WriteRequiredMap(
253254
writer.WriteMapInternal(name, elements, action);
254255
}
255256

257+
/// <summary>
258+
/// Write the optional Open API element map (string to string mapping).
259+
/// </summary>
260+
/// <param name="writer">The Open API writer.</param>
261+
/// <param name="name">The property name.</param>
262+
/// <param name="elements">The map values.</param>
263+
/// <param name="action">The map element writer action.</param>
264+
public static void WriteOptionalMap(
265+
this IOpenApiWriter writer,
266+
string name,
267+
IDictionary<string, JsonNode> elements,
268+
Action<IOpenApiWriter, JsonNode> action)
269+
{
270+
if (elements != null && elements.Any())
271+
{
272+
writer.WriteMapInternal(name, elements, action);
273+
}
274+
}
275+
256276
/// <summary>
257277
/// Write the optional Open API element map (string to string mapping).
258278
/// </summary>

0 commit comments

Comments
 (0)