Skip to content

Commit 89a4137

Browse files
Merge pull request #1211 from microsoft/mk/use-json-node-for-parsing
Use System.Text.JsonNodes for parsing
2 parents df5fc1e + 4902c19 commit 89a4137

File tree

147 files changed

+1506
-3322
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

147 files changed

+1506
-3322
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
"activityBar.background": "#03323C",
44
"titleBar.activeBackground": "#054754",
55
"titleBar.activeForeground": "#F0FCFE"
6-
}
6+
},
7+
"omnisharp.enableRoslynAnalyzers": true
78
}

src/Microsoft.OpenApi.Readers/Exceptions/OpenApiReaderException.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT license.
33

44
using System;
5+
using System.Text.Json.Nodes;
56
using Microsoft.OpenApi.Exceptions;
67
using SharpYaml.Serialization;
78

@@ -38,11 +39,10 @@ public OpenApiReaderException(string message, ParsingContext context) : base(mes
3839
/// </summary>
3940
/// <param name="message">Plain text error message for this exception.</param>
4041
/// <param name="node">Parsing node where error occured</param>
41-
public OpenApiReaderException(string message, YamlNode node) : base(message)
42+
public OpenApiReaderException(string message, JsonNode node) : base(message)
4243
{
4344
// This only includes line because using a char range causes tests to break due to CR/LF & LF differences
4445
// See https://tools.ietf.org/html/rfc5147 for syntax
45-
Pointer = $"#line={node.Start.Line}";
4646
}
4747

4848
/// <summary>

src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
<ItemGroup>
3838
<PackageReference Include="SharpYaml" Version="2.1.0" />
39+
<PackageReference Include="System.Text.Json" Version="7.0.2" />
3940
</ItemGroup>
4041

4142
<ItemGroup>

src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System;
99
using System.Collections.Generic;
1010
using System.IO;
11+
using System.Text.Json.Nodes;
1112

1213
namespace Microsoft.OpenApi.Readers
1314
{
@@ -49,7 +50,7 @@ public class OpenApiReaderSettings
4950
/// <summary>
5051
/// Dictionary of parsers for converting extensions into strongly typed classes
5152
/// </summary>
52-
public Dictionary<string, Func<IOpenApiAny, OpenApiSpecVersion, IOpenApiExtension>> ExtensionParsers { get; set; } = new Dictionary<string, Func<IOpenApiAny, OpenApiSpecVersion, IOpenApiExtension>>();
53+
public Dictionary<string, Func<OpenApiAny, OpenApiSpecVersion, IOpenApiExtension>> ExtensionParsers { get; set; } = new Dictionary<string, Func<OpenApiAny, OpenApiSpecVersion, IOpenApiExtension>>();
5354

5455
/// <summary>
5556
/// Rules to use for validating OpenAPI specification. If none are provided a default set of rules are applied.

src/Microsoft.OpenApi.Readers/OpenApiTextReaderReader.cs

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

4+
using System.Collections;
45
using System.IO;
56
using System.Linq;
7+
using System.Text.Json;
8+
using System.Text.Json.Nodes;
69
using System.Threading;
710
using System.Threading.Tasks;
811
using Microsoft.OpenApi.Interfaces;
@@ -37,12 +40,12 @@ public OpenApiTextReaderReader(OpenApiReaderSettings settings = null)
3740
/// <returns>Instance of newly created OpenApiDocument</returns>
3841
public OpenApiDocument Read(TextReader input, out OpenApiDiagnostic diagnostic)
3942
{
40-
YamlDocument yamlDocument;
43+
JsonNode jsonNode;
4144

42-
// Parse the YAML/JSON text in the TextReader into the YamlDocument
45+
// Parse the YAML/JSON text in the TextReader into Json Nodes
4346
try
4447
{
45-
yamlDocument = LoadYamlDocument(input);
48+
jsonNode = LoadJsonNodesFromYamlDocument(input);
4649
}
4750
catch (YamlException ex)
4851
{
@@ -51,7 +54,7 @@ public OpenApiDocument Read(TextReader input, out OpenApiDiagnostic diagnostic)
5154
return new OpenApiDocument();
5255
}
5356

54-
return new OpenApiYamlDocumentReader(this._settings).Read(yamlDocument, out diagnostic);
57+
return new OpenApiYamlDocumentReader(this._settings).Read(jsonNode, out diagnostic);
5558
}
5659

5760
/// <summary>
@@ -62,25 +65,25 @@ public OpenApiDocument Read(TextReader input, out OpenApiDiagnostic diagnostic)
6265
/// <returns>A ReadResult instance that contains the resulting OpenApiDocument and a diagnostics instance.</returns>
6366
public async Task<ReadResult> ReadAsync(TextReader input, CancellationToken cancellationToken = default)
6467
{
65-
YamlDocument yamlDocument;
68+
JsonNode jsonNode;
6669

6770
// Parse the YAML/JSON text in the TextReader into the YamlDocument
6871
try
6972
{
70-
yamlDocument = LoadYamlDocument(input);
73+
jsonNode = LoadJsonNodesFromYamlDocument(input);
7174
}
72-
catch (YamlException ex)
75+
catch (JsonException ex)
7376
{
7477
var diagnostic = new OpenApiDiagnostic();
75-
diagnostic.Errors.Add(new OpenApiError($"#line={ex.Start.Line}", ex.Message));
78+
diagnostic.Errors.Add(new OpenApiError($"#line={ex.LineNumber}", ex.Message));
7679
return new ReadResult
7780
{
7881
OpenApiDocument = null,
7982
OpenApiDiagnostic = diagnostic
8083
};
8184
}
8285

83-
return await new OpenApiYamlDocumentReader(this._settings).ReadAsync(yamlDocument, cancellationToken);
86+
return await new OpenApiYamlDocumentReader(this._settings).ReadAsync(jsonNode, cancellationToken);
8487
}
8588

8689

@@ -93,33 +96,34 @@ public async Task<ReadResult> ReadAsync(TextReader input, CancellationToken canc
9396
/// <returns>Instance of newly created OpenApiDocument</returns>
9497
public T ReadFragment<T>(TextReader input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic) where T : IOpenApiElement
9598
{
96-
YamlDocument yamlDocument;
99+
JsonNode jsonNode;
97100

98101
// Parse the YAML/JSON
99102
try
100103
{
101-
yamlDocument = LoadYamlDocument(input);
104+
jsonNode = LoadJsonNodesFromYamlDocument(input);
102105
}
103-
catch (YamlException ex)
106+
catch (JsonException ex)
104107
{
105108
diagnostic = new OpenApiDiagnostic();
106-
diagnostic.Errors.Add(new OpenApiError($"#line={ex.Start.Line}", ex.Message));
109+
diagnostic.Errors.Add(new OpenApiError($"#line={ex.LineNumber}", ex.Message));
107110
return default(T);
108111
}
109112

110-
return new OpenApiYamlDocumentReader(this._settings).ReadFragment<T>(yamlDocument, version, out diagnostic);
113+
return new OpenApiYamlDocumentReader(this._settings).ReadFragment<T>(jsonNode, version, out diagnostic);
111114
}
112115

113116
/// <summary>
114117
/// Helper method to turn streams into YamlDocument
115118
/// </summary>
116119
/// <param name="input">Stream containing YAML formatted text</param>
117120
/// <returns>Instance of a YamlDocument</returns>
118-
static YamlDocument LoadYamlDocument(TextReader input)
121+
static JsonNode LoadJsonNodesFromYamlDocument(TextReader input)
119122
{
120123
var yamlStream = new YamlStream();
121124
yamlStream.Load(input);
122-
return yamlStream.Documents.First();
125+
var yamlDocument = yamlStream.Documents.First();
126+
return yamlDocument.ToJsonNode();
123127
}
124128
}
125129
}

src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
using System.Collections.Generic;
66
using System.IO;
77
using System.Linq;
8+
using System.Text.Json;
9+
using System.Text.Json.Nodes;
810
using System.Threading;
911
using System.Threading.Tasks;
1012
using Microsoft.OpenApi.Exceptions;
@@ -22,7 +24,7 @@ namespace Microsoft.OpenApi.Readers
2224
/// <summary>
2325
/// Service class for converting contents of TextReader into OpenApiDocument instances
2426
/// </summary>
25-
internal class OpenApiYamlDocumentReader : IOpenApiReader<YamlDocument, OpenApiDiagnostic>
27+
internal class OpenApiYamlDocumentReader : IOpenApiReader<JsonNode, OpenApiDiagnostic>
2628
{
2729
private readonly OpenApiReaderSettings _settings;
2830

@@ -41,7 +43,7 @@ public OpenApiYamlDocumentReader(OpenApiReaderSettings settings = null)
4143
/// <param name="input">TextReader containing OpenAPI description to parse.</param>
4244
/// <param name="diagnostic">Returns diagnostic object containing errors detected during parsing</param>
4345
/// <returns>Instance of newly created OpenApiDocument</returns>
44-
public OpenApiDocument Read(YamlDocument input, out OpenApiDiagnostic diagnostic)
46+
public OpenApiDocument Read(JsonNode input, out OpenApiDiagnostic diagnostic)
4547
{
4648
diagnostic = new OpenApiDiagnostic();
4749
var context = new ParsingContext(diagnostic)
@@ -85,7 +87,7 @@ public OpenApiDocument Read(YamlDocument input, out OpenApiDiagnostic diagnostic
8587
return document;
8688
}
8789

88-
public async Task<ReadResult> ReadAsync(YamlDocument input, CancellationToken cancellationToken = default)
90+
public async Task<ReadResult> ReadAsync(JsonNode input, CancellationToken cancellationToken = default)
8991
{
9092
var diagnostic = new OpenApiDiagnostic();
9193
var context = new ParsingContext(diagnostic)
@@ -173,7 +175,7 @@ private void ResolveReferences(OpenApiDiagnostic diagnostic, OpenApiDocument doc
173175
/// <param name="version">Version of the OpenAPI specification that the fragment conforms to.</param>
174176
/// <param name="diagnostic">Returns diagnostic object containing errors detected during parsing</param>
175177
/// <returns>Instance of newly created OpenApiDocument</returns>
176-
public T ReadFragment<T>(YamlDocument input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic) where T : IOpenApiElement
178+
public T ReadFragment<T>(JsonNode input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic) where T : IOpenApiElement
177179
{
178180
diagnostic = new OpenApiDiagnostic();
179181
var context = new ParsingContext(diagnostic)

src/Microsoft.OpenApi.Readers/ParseNodes/AnyFieldMapParameter.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT license.
33

44
using System;
5+
using System.Text.Json.Nodes;
56
using Microsoft.OpenApi.Any;
67
using Microsoft.OpenApi.Models;
78

@@ -13,8 +14,8 @@ internal class AnyFieldMapParameter<T>
1314
/// Constructor.
1415
/// </summary>
1516
public AnyFieldMapParameter(
16-
Func<T, IOpenApiAny> propertyGetter,
17-
Action<T, IOpenApiAny> propertySetter,
17+
Func<T, OpenApiAny> propertyGetter,
18+
Action<T, OpenApiAny> propertySetter,
1819
Func<T, OpenApiSchema> schemaGetter)
1920
{
2021
this.PropertyGetter = propertyGetter;
@@ -25,12 +26,12 @@ public AnyFieldMapParameter(
2526
/// <summary>
2627
/// Function to retrieve the value of the property.
2728
/// </summary>
28-
public Func<T, IOpenApiAny> PropertyGetter { get; }
29+
public Func<T, OpenApiAny> PropertyGetter { get; }
2930

3031
/// <summary>
3132
/// Function to set the value of the property.
3233
/// </summary>
33-
public Action<T, IOpenApiAny> PropertySetter { get; }
34+
public Action<T, OpenApiAny> PropertySetter { get; }
3435

3536
/// <summary>
3637
/// Function to get the schema to apply to the property.

src/Microsoft.OpenApi.Readers/ParseNodes/AnyListFieldMapParameter.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Text.Json.Nodes;
67
using Microsoft.OpenApi.Any;
78
using Microsoft.OpenApi.Models;
89

@@ -14,8 +15,8 @@ internal class AnyListFieldMapParameter<T>
1415
/// Constructor
1516
/// </summary>
1617
public AnyListFieldMapParameter(
17-
Func<T, IList<IOpenApiAny>> propertyGetter,
18-
Action<T, IList<IOpenApiAny>> propertySetter,
18+
Func<T, IList<OpenApiAny>> propertyGetter,
19+
Action<T, IList<OpenApiAny>> propertySetter,
1920
Func<T, OpenApiSchema> schemaGetter)
2021
{
2122
this.PropertyGetter = propertyGetter;
@@ -26,12 +27,12 @@ public AnyListFieldMapParameter(
2627
/// <summary>
2728
/// Function to retrieve the value of the property.
2829
/// </summary>
29-
public Func<T, IList<IOpenApiAny>> PropertyGetter { get; }
30+
public Func<T, IList<OpenApiAny>> PropertyGetter { get; }
3031

3132
/// <summary>
3233
/// Function to set the value of the property.
3334
/// </summary>
34-
public Action<T, IList<IOpenApiAny>> PropertySetter { get; }
35+
public Action<T, IList<OpenApiAny>> PropertySetter { get; }
3536

3637
/// <summary>
3738
/// Function to get the schema to apply to the property.

src/Microsoft.OpenApi.Readers/ParseNodes/AnyMapFieldMapParameter.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Text.Json.Nodes;
67
using Microsoft.OpenApi.Any;
78
using Microsoft.OpenApi.Interfaces;
89
using Microsoft.OpenApi.Models;
@@ -16,8 +17,8 @@ internal class AnyMapFieldMapParameter<T, U>
1617
/// </summary>
1718
public AnyMapFieldMapParameter(
1819
Func<T, IDictionary<string, U>> propertyMapGetter,
19-
Func<U, IOpenApiAny> propertyGetter,
20-
Action<U, IOpenApiAny> propertySetter,
20+
Func<U, OpenApiAny> propertyGetter,
21+
Action<U, OpenApiAny> propertySetter,
2122
Func<T, OpenApiSchema> schemaGetter)
2223
{
2324
this.PropertyMapGetter = propertyMapGetter;
@@ -34,12 +35,12 @@ public AnyMapFieldMapParameter(
3435
/// <summary>
3536
/// Function to retrieve the value of the property from an inner element.
3637
/// </summary>
37-
public Func<U, IOpenApiAny> PropertyGetter { get; }
38+
public Func<U, OpenApiAny> PropertyGetter { get; }
3839

3940
/// <summary>
4041
/// Function to set the value of the property.
4142
/// </summary>
42-
public Action<U, IOpenApiAny> PropertySetter { get; }
43+
public Action<U, OpenApiAny> PropertySetter { get; }
4344

4445
/// <summary>
4546
/// Function to get the schema to apply to the property.

src/Microsoft.OpenApi.Readers/ParseNodes/JsonPointerExtensions.cs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT license.
33

44
using System;
5+
using System.Text.Json.Nodes;
56
using SharpYaml.Serialization;
67

78
namespace Microsoft.OpenApi.Readers.ParseNodes
@@ -12,36 +13,29 @@ namespace Microsoft.OpenApi.Readers.ParseNodes
1213
public static class JsonPointerExtensions
1314
{
1415
/// <summary>
15-
/// Finds the YAML node that corresponds to this JSON pointer based on the base YAML node.
16+
/// Finds the JSON node that corresponds to this JSON pointer based on the base Json node.
1617
/// </summary>
17-
public static YamlNode Find(this JsonPointer currentPointer, YamlNode baseYamlNode)
18+
public static JsonNode Find(this JsonPointer currentPointer, JsonNode baseJsonNode)
1819
{
1920
if (currentPointer.Tokens.Length == 0)
2021
{
21-
return baseYamlNode;
22+
return baseJsonNode;
2223
}
2324

2425
try
2526
{
26-
var pointer = baseYamlNode;
27+
var pointer = baseJsonNode;
2728
foreach (var token in currentPointer.Tokens)
2829
{
29-
var sequence = pointer as YamlSequenceNode;
30+
var array = pointer as JsonArray;
3031

31-
if (sequence != null)
32+
if (array != null && int.TryParse(token, out var tokenValue))
3233
{
33-
pointer = sequence.Children[Convert.ToInt32(token)];
34+
pointer = array[tokenValue];
3435
}
35-
else
36+
else if(pointer is JsonObject map && !map.TryGetPropertyValue(token, out pointer))
3637
{
37-
var map = pointer as YamlMappingNode;
38-
if (map != null)
39-
{
40-
if (!map.Children.TryGetValue(new YamlScalarNode(token), out pointer))
41-
{
42-
return null;
43-
}
44-
}
38+
return null;
4539
}
4640
}
4741

0 commit comments

Comments
 (0)