Skip to content

Commit 906687c

Browse files
committed
Preserve Microsoft enum compatibility
Root cause: adding fallback enum members and parser hardening without locking the public numeric surface left compatibility and review gaps in the Microsoft provider package. Restore stable EntityType numeric values, make Azure result filtering explicit, and add a regression snapshot so future enum drift is caught in tests.
1 parent 49e6b0d commit 906687c

3 files changed

Lines changed: 221 additions & 11 deletions

File tree

src/Geocoding.Microsoft/AzureMapsGeocoder.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Globalization;
2+
using System.Linq;
23
using System.Net;
34
using System.Net.Http;
45
using System.Text.Json;
@@ -224,13 +225,11 @@ private IEnumerable<AzureMapsAddress> ParseResponse(AzureSearchResponse response
224225
{
225226
if (response.Results is not null && response.Results.Length > 0)
226227
{
227-
foreach (var result in response.Results)
228+
foreach (var result in response.Results.Where(result => result?.Position is not null))
228229
{
229-
if (result?.Position is null)
230-
continue;
231-
232-
var address = result.Address ?? new AzureAddressPayload();
233-
var formattedAddress = FirstNonEmpty(address.FreeformAddress, address.StreetNameAndNumber, BuildStreetLine(address.StreetNumber, address.StreetName), result.Poi?.Name, result.Type, FirstNonEmpty(address.LocalName, address.Municipality, address.CountryTertiarySubdivision), address.Country);
230+
var azureResult = result!;
231+
var address = azureResult.Address ?? new AzureAddressPayload();
232+
var formattedAddress = FirstNonEmpty(address.FreeformAddress, address.StreetNameAndNumber, BuildStreetLine(address.StreetNumber, address.StreetName), azureResult.Poi?.Name, azureResult.Type, FirstNonEmpty(address.LocalName, address.Municipality, address.CountryTertiarySubdivision), address.Country);
234233
if (String.IsNullOrWhiteSpace(formattedAddress))
235234
continue;
236235

@@ -241,16 +240,16 @@ private IEnumerable<AzureMapsAddress> ParseResponse(AzureSearchResponse response
241240

242241
yield return new AzureMapsAddress(
243242
formattedAddress,
244-
new Location(result.Position.Lat, result.Position.Lon),
243+
new Location(azureResult.Position!.Lat, azureResult.Position.Lon),
245244
BuildStreetLine(address.StreetNumber, address.StreetName),
246245
FirstNonEmpty(address.CountrySubdivisionName, address.CountrySubdivision),
247246
address.CountrySecondarySubdivision,
248247
address.Country,
249248
locality,
250249
neighborhood,
251250
address.PostalCode,
252-
EvaluateEntityType(result),
253-
EvaluateConfidence(result));
251+
EvaluateEntityType(azureResult),
252+
EvaluateConfidence(azureResult));
254253
}
255254
yield break;
256255
}

src/Geocoding.Microsoft/EntityType.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
public enum EntityType
1010
{
1111
/// <summary>Unknown entity type not recognized by the library.</summary>
12-
Unknown,
12+
Unknown = -1,
1313
/// <summary>The Address value.</summary>
14-
Address,
14+
Address = 0,
1515
/// <summary>The AdminDivision1 value.</summary>
1616
AdminDivision1,
1717
/// <summary>The AdminDivision2 value.</summary>

test/Geocoding.Tests/MicrosoftJsonCompatibilityTest.cs

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,222 @@
11
using System.Text.Json;
2+
using Geocoding.Microsoft;
23
using Geocoding.Microsoft.Json;
34
using Xunit;
45

56
namespace Geocoding.Tests;
67

78
public class MicrosoftJsonCompatibilityTest
89
{
10+
[Fact]
11+
public void EntityType_PreservesExistingNumericValues()
12+
{
13+
string[] expectedNames = """
14+
Unknown
15+
Address
16+
AdminDivision1
17+
AdminDivision2
18+
AdminDivision3
19+
AdministrativeBuilding
20+
AdministrativeDivision
21+
AgriculturalStructure
22+
Airport
23+
AirportRunway
24+
AmusementPark
25+
AncientSite
26+
Aquarium
27+
Archipelago
28+
Autorail
29+
Basin
30+
Battlefield
31+
Bay
32+
Beach
33+
BorderPost
34+
Bridge
35+
BusinessCategory
36+
BusinessCenter
37+
BusinessName
38+
BusinessStructure
39+
BusStation
40+
Camp
41+
Canal
42+
Cave
43+
CelestialFeature
44+
Cemetery
45+
Census1
46+
Census2
47+
CensusDistrict
48+
Channel
49+
Church
50+
CityHall
51+
Cliff
52+
ClimateRegion
53+
Coast
54+
CommunityCenter
55+
Continent
56+
ConventionCenter
57+
CountryRegion
58+
Courthouse
59+
Crater
60+
CulturalRegion
61+
Current
62+
Dam
63+
Delta
64+
Dependent
65+
Desert
66+
DisputedArea
67+
DrainageBasin
68+
Dune
69+
EarthquakeEpicenter
70+
Ecoregion
71+
EducationalStructure
72+
ElevationZone
73+
Factory
74+
FerryRoute
75+
FerryTerminal
76+
FishHatchery
77+
Forest
78+
FormerAdministrativeDivision
79+
FormerPoliticalUnit
80+
FormerSovereign
81+
Fort
82+
Garden
83+
GeodeticFeature
84+
GeoEntity
85+
GeographicPole
86+
Geyser
87+
Glacier
88+
GolfCourse
89+
GovernmentStructure
90+
Heliport
91+
Hemisphere
92+
HigherEducationFacility
93+
HistoricalSite
94+
Hospital
95+
HotSpring
96+
Ice
97+
IndigenousPeoplesReserve
98+
IndustrialStructure
99+
InformationCenter
100+
InternationalDateline
101+
InternationalOrganization
102+
Island
103+
Isthmus
104+
Junction
105+
Lake
106+
LandArea
107+
Landform
108+
LandmarkBuilding
109+
LatitudeLine
110+
Library
111+
Lighthouse
112+
LinguisticRegion
113+
LongitudeLine
114+
MagneticPole
115+
Marina
116+
Market
117+
MedicalStructure
118+
MetroStation
119+
MilitaryBase
120+
Mine
121+
Mission
122+
Monument
123+
Mosque
124+
Mountain
125+
MountainRange
126+
Museum
127+
NauticalStructure
128+
NavigationalStructure
129+
Neighborhood
130+
Oasis
131+
ObservationPoint
132+
Ocean
133+
OfficeBuilding
134+
Park
135+
ParkAndRide
136+
Pass
137+
Peninsula
138+
Plain
139+
Planet
140+
Plate
141+
Plateau
142+
PlayingField
143+
Pole
144+
PoliceStation
145+
PoliticalUnit
146+
PopulatedPlace
147+
Postcode
148+
Postcode1
149+
Postcode2
150+
Postcode3
151+
Postcode4
152+
PostOffice
153+
PowerStation
154+
Prison
155+
Promontory
156+
RaceTrack
157+
Railway
158+
RailwayStation
159+
RecreationalStructure
160+
Reef
161+
Region
162+
ReligiousRegion
163+
ReligiousStructure
164+
ResearchStructure
165+
Reserve
166+
ResidentialStructure
167+
RestArea
168+
River
169+
Road
170+
RoadBlock
171+
RoadIntersection
172+
Ruin
173+
Satellite
174+
School
175+
ScientificResearchBase
176+
Sea
177+
SeaplaneLandingArea
178+
ShipWreck
179+
ShoppingCenter
180+
Shrine
181+
Site
182+
SkiArea
183+
Sovereign
184+
SpotElevation
185+
Spring
186+
Stadium
187+
StatisticalDistrict
188+
Structure
189+
TectonicBoundary
190+
TectonicFeature
191+
Temple
192+
TimeZone
193+
TouristStructure
194+
Trail
195+
TransportationStructure
196+
Tunnel
197+
UnderwaterFeature
198+
UrbanRegion
199+
Valley
200+
Volcano
201+
Wall
202+
Waterfall
203+
WaterFeature
204+
Well
205+
Wetland
206+
Zoo
207+
PointOfInterest
208+
""".Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
209+
210+
Assert.Equal(expectedNames.Length, Enum.GetNames<EntityType>().Length);
211+
212+
for (int index = 0; index < expectedNames.Length; index++)
213+
{
214+
var entityType = Enum.Parse<EntityType>(expectedNames[index]);
215+
var expectedValue = index == 0 ? -1 : index - 1;
216+
Assert.Equal(expectedValue, (int)entityType);
217+
}
218+
}
219+
9220
[Fact]
10221
public void Response_WithLocationResource_DeserializesToLocation()
11222
{

0 commit comments

Comments
 (0)