Skip to content

Commit e8f55b1

Browse files
authored
Merge pull request #326 from Microsoft/perthcharern/FixCultureInfo
Parse decimals and ints with InvariantCulture since JSON/YAML doesn't vary by culture.
2 parents 9aa3e97 + 1a8cdc9 commit e8f55b1

File tree

9 files changed

+189
-35
lines changed

9 files changed

+189
-35
lines changed

src/Microsoft.OpenApi.Readers/V2/OpenApiDocumentDeserializer.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Globalization;
67
using System.Linq;
78
using Microsoft.OpenApi.Extensions;
89
using Microsoft.OpenApi.Interfaces;
@@ -191,7 +192,7 @@ private static string BuildUrl(string scheme, string host, string basePath)
191192
{
192193
var pieces = host.Split(':');
193194
host = pieces.First();
194-
port = int.Parse(pieces.Last());
195+
port = int.Parse(pieces.Last(), CultureInfo.InvariantCulture);
195196
}
196197

197198
var uriBuilder = new UriBuilder()

src/Microsoft.OpenApi.Readers/V2/OpenApiHeaderDeserializer.cs

Lines changed: 9 additions & 8 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.Globalization;
56
using Microsoft.OpenApi.Any;
67
using Microsoft.OpenApi.Extensions;
78
using Microsoft.OpenApi.Models;
@@ -54,10 +55,10 @@ internal static partial class OpenApiV2Deserializer
5455
GetOrCreateSchema(o).Default = n.CreateAny();
5556
}
5657
},
57-
{
58+
{
5859
"maximum", (o, n) =>
5960
{
60-
GetOrCreateSchema(o).Maximum = decimal.Parse(n.GetScalarValue());
61+
GetOrCreateSchema(o).Maximum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
6162
}
6263
},
6364
{
@@ -69,7 +70,7 @@ internal static partial class OpenApiV2Deserializer
6970
{
7071
"minimum", (o, n) =>
7172
{
72-
GetOrCreateSchema(o).Minimum = decimal.Parse(n.GetScalarValue());
73+
GetOrCreateSchema(o).Minimum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
7374
}
7475
},
7576
{
@@ -81,13 +82,13 @@ internal static partial class OpenApiV2Deserializer
8182
{
8283
"maxLength", (o, n) =>
8384
{
84-
GetOrCreateSchema(o).MaxLength = int.Parse(n.GetScalarValue());
85+
GetOrCreateSchema(o).MaxLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
8586
}
8687
},
8788
{
8889
"minLength", (o, n) =>
8990
{
90-
GetOrCreateSchema(o).MinLength = int.Parse(n.GetScalarValue());
91+
GetOrCreateSchema(o).MinLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
9192
}
9293
},
9394
{
@@ -99,13 +100,13 @@ internal static partial class OpenApiV2Deserializer
99100
{
100101
"maxItems", (o, n) =>
101102
{
102-
GetOrCreateSchema(o).MaxItems = int.Parse(n.GetScalarValue());
103+
GetOrCreateSchema(o).MaxItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
103104
}
104105
},
105106
{
106107
"minItems", (o, n) =>
107108
{
108-
GetOrCreateSchema(o).MinItems = int.Parse(n.GetScalarValue());
109+
GetOrCreateSchema(o).MinItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
109110
}
110111
},
111112
{
@@ -117,7 +118,7 @@ internal static partial class OpenApiV2Deserializer
117118
{
118119
"multipleOf", (o, n) =>
119120
{
120-
GetOrCreateSchema(o).MultipleOf = decimal.Parse(n.GetScalarValue());
121+
GetOrCreateSchema(o).MultipleOf = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
121122
}
122123
},
123124
{

src/Microsoft.OpenApi.Readers/V2/OpenApiParameterDeserializer.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.Globalization;
67
using Microsoft.OpenApi.Any;
78
using Microsoft.OpenApi.Extensions;
89
using Microsoft.OpenApi.Models;
@@ -90,25 +91,25 @@ internal static partial class OpenApiV2Deserializer
9091
{
9192
"minimum", (o, n) =>
9293
{
93-
GetOrCreateSchema(o).Minimum = decimal.Parse(n.GetScalarValue());
94+
GetOrCreateSchema(o).Minimum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
9495
}
9596
},
9697
{
9798
"maximum", (o, n) =>
9899
{
99-
GetOrCreateSchema(o).Maximum = decimal.Parse(n.GetScalarValue());
100+
GetOrCreateSchema(o).Maximum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
100101
}
101102
},
102103
{
103104
"maxLength", (o, n) =>
104105
{
105-
GetOrCreateSchema(o).MaxLength = int.Parse(n.GetScalarValue());
106+
GetOrCreateSchema(o).MaxLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
106107
}
107108
},
108109
{
109110
"minLength", (o, n) =>
110111
{
111-
GetOrCreateSchema(o).MinLength = int.Parse(n.GetScalarValue());
112+
GetOrCreateSchema(o).MinLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
112113
}
113114
},
114115
{

src/Microsoft.OpenApi.Readers/V2/OpenApiSchemaDeserializer.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Microsoft.OpenApi.Models;
77
using Microsoft.OpenApi.Readers.ParseNodes;
88
using System.Collections.Generic;
9+
using System.Globalization;
910

1011
namespace Microsoft.OpenApi.Readers.V2
1112
{
@@ -26,13 +27,13 @@ internal static partial class OpenApiV2Deserializer
2627
{
2728
"multipleOf", (o, n) =>
2829
{
29-
o.MultipleOf = decimal.Parse(n.GetScalarValue());
30+
o.MultipleOf = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
3031
}
3132
},
3233
{
3334
"maximum", (o, n) =>
3435
{
35-
o.Maximum = decimal.Parse(n.GetScalarValue());
36+
o.Maximum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
3637
}
3738
},
3839
{
@@ -44,7 +45,7 @@ internal static partial class OpenApiV2Deserializer
4445
{
4546
"minimum", (o, n) =>
4647
{
47-
o.Minimum = decimal.Parse(n.GetScalarValue());
48+
o.Minimum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
4849
}
4950
},
5051
{
@@ -56,13 +57,13 @@ internal static partial class OpenApiV2Deserializer
5657
{
5758
"maxLength", (o, n) =>
5859
{
59-
o.MaxLength = int.Parse(n.GetScalarValue());
60+
o.MaxLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
6061
}
6162
},
6263
{
6364
"minLength", (o, n) =>
6465
{
65-
o.MinLength = int.Parse(n.GetScalarValue());
66+
o.MinLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
6667
}
6768
},
6869
{
@@ -74,13 +75,13 @@ internal static partial class OpenApiV2Deserializer
7475
{
7576
"maxItems", (o, n) =>
7677
{
77-
o.MaxItems = int.Parse(n.GetScalarValue());
78+
o.MaxItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
7879
}
7980
},
8081
{
8182
"minItems", (o, n) =>
8283
{
83-
o.MinItems = int.Parse(n.GetScalarValue());
84+
o.MinItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
8485
}
8586
},
8687
{
@@ -92,13 +93,13 @@ internal static partial class OpenApiV2Deserializer
9293
{
9394
"maxProperties", (o, n) =>
9495
{
95-
o.MaxProperties = int.Parse(n.GetScalarValue());
96+
o.MaxProperties = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
9697
}
9798
},
9899
{
99100
"minProperties", (o, n) =>
100101
{
101-
o.MinProperties = int.Parse(n.GetScalarValue());
102+
o.MinProperties = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
102103
}
103104
},
104105
{

src/Microsoft.OpenApi.Readers/V3/OpenApiSchemaDeserializer.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Microsoft.OpenApi.Models;
77
using Microsoft.OpenApi.Readers.ParseNodes;
88
using System.Collections.Generic;
9+
using System.Globalization;
910

1011
namespace Microsoft.OpenApi.Readers.V3
1112
{
@@ -26,13 +27,13 @@ internal static partial class OpenApiV3Deserializer
2627
{
2728
"multipleOf", (o, n) =>
2829
{
29-
o.MultipleOf = decimal.Parse(n.GetScalarValue());
30+
o.MultipleOf = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
3031
}
3132
},
3233
{
3334
"maximum", (o, n) =>
3435
{
35-
o.Maximum = decimal.Parse(n.GetScalarValue());
36+
o.Maximum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
3637
}
3738
},
3839
{
@@ -44,7 +45,7 @@ internal static partial class OpenApiV3Deserializer
4445
{
4546
"minimum", (o, n) =>
4647
{
47-
o.Minimum = decimal.Parse(n.GetScalarValue());
48+
o.Minimum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
4849
}
4950
},
5051
{
@@ -56,13 +57,13 @@ internal static partial class OpenApiV3Deserializer
5657
{
5758
"maxLength", (o, n) =>
5859
{
59-
o.MaxLength = int.Parse(n.GetScalarValue());
60+
o.MaxLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
6061
}
6162
},
6263
{
6364
"minLength", (o, n) =>
6465
{
65-
o.MinLength = int.Parse(n.GetScalarValue());
66+
o.MinLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
6667
}
6768
},
6869
{
@@ -74,13 +75,13 @@ internal static partial class OpenApiV3Deserializer
7475
{
7576
"maxItems", (o, n) =>
7677
{
77-
o.MaxItems = int.Parse(n.GetScalarValue());
78+
o.MaxItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
7879
}
7980
},
8081
{
8182
"minItems", (o, n) =>
8283
{
83-
o.MinItems = int.Parse(n.GetScalarValue());
84+
o.MinItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
8485
}
8586
},
8687
{
@@ -92,13 +93,13 @@ internal static partial class OpenApiV3Deserializer
9293
{
9394
"maxProperties", (o, n) =>
9495
{
95-
o.MaxProperties = int.Parse(n.GetScalarValue());
96+
o.MaxProperties = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
9697
}
9798
},
9899
{
99100
"minProperties", (o, n) =>
100101
{
101-
o.MinProperties = int.Parse(n.GetScalarValue());
102+
o.MinProperties = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture);
102103
}
103104
},
104105
{

test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs

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

44
using System.Collections.Generic;
5+
using System.Globalization;
6+
using System.Threading;
57
using FluentAssertions;
68
using Microsoft.OpenApi.Exceptions;
79
using Microsoft.OpenApi.Models;
@@ -66,5 +68,76 @@ public void ShouldThrowWhenReferenceDoesNotExist()
6668
new OpenApiError( new OpenApiException("Invalid Reference identifier 'doesnotexist'.")) });
6769
doc.Should().NotBeNull();
6870
}
71+
72+
[Theory]
73+
[InlineData("en-US")]
74+
[InlineData("hi-IN")]
75+
// The equivalent of English 1,000.36 in French and Danish is 1.000,36
76+
[InlineData("fr-FR")]
77+
[InlineData("da-DK")]
78+
public void ParseDocumentWithDifferentCultureShouldSucceed(string culture)
79+
{
80+
Thread.CurrentThread.CurrentCulture = new CultureInfo(culture);
81+
Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
82+
83+
var openApiDoc = new OpenApiStringReader().Read(
84+
@"
85+
swagger: 2.0
86+
info:
87+
title: Simple Document
88+
version: 0.9.1
89+
definitions:
90+
sampleSchema:
91+
type: object
92+
properties:
93+
sampleProperty:
94+
type: double
95+
minimum: 100.54
96+
maximum: 60,000,000.35
97+
exclusiveMaximum: true
98+
exclusiveMinimum: false
99+
paths: {}",
100+
out var context);
101+
102+
openApiDoc.ShouldBeEquivalentTo(
103+
new OpenApiDocument
104+
{
105+
Info = new OpenApiInfo
106+
{
107+
Title = "Simple Document",
108+
Version = "0.9.1"
109+
},
110+
Components = new OpenApiComponents()
111+
{
112+
Schemas =
113+
{
114+
["sampleSchema"] = new OpenApiSchema()
115+
{
116+
Type = "object",
117+
Properties =
118+
{
119+
["sampleProperty"] = new OpenApiSchema()
120+
{
121+
Type = "double",
122+
Minimum = (decimal)100.54,
123+
Maximum = (decimal)60000000.35,
124+
ExclusiveMaximum = true,
125+
ExclusiveMinimum = false
126+
}
127+
},
128+
Reference = new OpenApiReference()
129+
{
130+
Id = "sampleSchema",
131+
Type = ReferenceType.Schema
132+
}
133+
}
134+
}
135+
},
136+
Paths = new OpenApiPaths()
137+
});
138+
139+
context.ShouldBeEquivalentTo(
140+
new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi2_0 });
141+
}
69142
}
70143
}

0 commit comments

Comments
 (0)