Skip to content
Open
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
968bcc8
SpatialPoint Serialization/Deserialization: Fixes spatial point seria…
dibahlfi Oct 11, 2024
bf9bb6e
SpatialPoint Serialization/Deserialization: Fixes spatial point seria…
dibahlfi Oct 21, 2024
35b4846
WIP: STJ Serialization/DeSerialization
dibahlfi Oct 28, 2024
b3193f1
WIP: STJ Serialization/DeSerialization
dibahlfi Oct 31, 2024
9cb6ccb
WIP: STJ Serialization/DeSerialization
dibahlfi Nov 1, 2024
8564f03
WIP: STJ Serialization/DeSerialization
dibahlfi Nov 4, 2024
a3fca0c
WIP: STJ Serialization/DeSerialization
dibahlfi Nov 4, 2024
d38562a
WIP: STJ Serialization/DeSerialization
dibahlfi Nov 4, 2024
036f213
WIP: STJ Serialization/DeSerialization
dibahlfi Nov 5, 2024
3f62825
refactoring: matching STJ serialization/de format same as newtonsoft …
dibahlfi Aug 8, 2025
922cea7
cleaning up
dibahlfi Aug 8, 2025
c33db60
cleaning up
dibahlfi Aug 8, 2025
d2c6015
cleaning up
dibahlfi Aug 8, 2025
74a0aff
cleaning up
dibahlfi Aug 8, 2025
6186e66
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Jan 16, 2026
e02b884
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Jan 23, 2026
7c2b5b7
Merge remote-tracking branch 'origin/master' into users/dikshibahl/Sp…
NaluTripician Jan 29, 2026
03dde96
added comments for clarity and tests
NaluTripician Jan 29, 2026
23eb888
test fixes
NaluTripician Jan 29, 2026
12372b0
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Feb 2, 2026
017e413
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Feb 17, 2026
62c5ff1
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Feb 17, 2026
2162340
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Feb 23, 2026
3b996d4
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
kirankumarkolli Feb 24, 2026
23e949d
[Internal/Ignore] Spatial Serialization: Fixes JsonElement.Deserializ…
Copilot Feb 25, 2026
5416e55
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Mar 3, 2026
7e5e11c
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Mar 4, 2026
fa6c6e7
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Mar 10, 2026
b9bbe65
Tests: Adds PatchItemAsync test case for spatial point serialization
NaluTripician Mar 10, 2026
27852c5
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Mar 11, 2026
06d999b
Tests: Fixes PatchOperation path in STJ spatial serialization test
NaluTripician Mar 11, 2026
8600e02
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Mar 17, 2026
46673e8
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Mar 17, 2026
c7cff42
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Mar 18, 2026
0e10fd3
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Mar 18, 2026
9bcadcd
Address review feedback: use STJMetaDataFields constants and RMResources
NaluTripician Mar 19, 2026
2bbcef2
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Mar 19, 2026
1c597e8
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Mar 24, 2026
0f21a4a
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Mar 24, 2026
1acee99
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Mar 31, 2026
7e986f0
Merge branch 'master' into users/dikshibahl/SpatialPointSerializationBug
NaluTripician Apr 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Microsoft.Azure.Cosmos/src/Spatial/BoundingBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ namespace Microsoft.Azure.Cosmos.Spatial
using System;
using System.Runtime.Serialization;
using Microsoft.Azure.Cosmos.Spatial.Converters;
using Microsoft.Azure.Cosmos.Spatial.Converters.STJConverters;
using Newtonsoft.Json;

/// <summary>
/// Represents a coordinate range for geometries in the Azure Cosmos DB service.
/// </summary>
[DataContract]
[JsonConverter(typeof(BoundingBoxJsonConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(BoundingBoxSTJConverter))]
public sealed class BoundingBox : IEquatable<BoundingBox>
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public override object ReadJson(
throw new JsonSerializationException(RMResources.SpatialFailedToDeserializeCrs);
}

return new LinkedCrs(crsHref.Value<string>(), crsHrefType.Value<string>());
return new LinkedCrs(crsHref.Value<string>(), crsHrefType?.Value<string>());

default:
throw new JsonSerializationException(RMResources.SpatialFailedToDeserializeCrs);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Spatial.Converters.STJConverters
{
using System;
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Azure.Documents;
/// <summary>
/// Converter used to support System.Text.Json serialization/deserialization of BoundingBox.
/// </summary>
internal sealed class BoundingBoxSTJConverter : JsonConverter<BoundingBox>
{
/// <summary>
/// Deserializes a BoundingBox from a JSON array of coordinates.
/// The array contains min coordinates followed by max coordinates.
/// Example: [minLon, minLat, maxLon, maxLat] for 2D or [minLon, minLat, minAlt, maxLon, maxLat, maxAlt] for 3D.
/// </summary>
public override BoundingBox Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
double[] coordinates = JsonSerializer.Deserialize<double[]>(ref reader, options);
if (coordinates == null)
{
return null;
}

if (coordinates.Length % 2 != 0 || coordinates.Length < 4)
{
throw new JsonException(RMResources.SpatialBoundingBoxInvalidCoordinates);
}

return new BoundingBox(
new Position(coordinates.Take(coordinates.Length / 2).ToList()),
new Position(coordinates.Skip(coordinates.Length / 2).ToList()));
}

/// <summary>
/// Serializes a BoundingBox to a JSON array.
/// Outputs min coordinates followed by max coordinates.
/// </summary>
public override void Write(Utf8JsonWriter writer, BoundingBox box, JsonSerializerOptions options)
{
writer.WriteStartArray();
foreach (double coordinate in box.Min.Coordinates.Concat(box.Max.Coordinates))
{
// Check if the number is effectively an integer.
if (coordinate == Math.Truncate(coordinate))
{
// If so, write it with one decimal place to match Newtonsoft's [x.0] format.
writer.WriteRawValue(coordinate.ToString("0.0", CultureInfo.InvariantCulture));
}
else
{
writer.WriteRawValue(coordinate.ToString("R", CultureInfo.InvariantCulture));
}
}
writer.WriteEndArray();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Spatial.Converters.STJConverters
{
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Azure.Documents;
/// <summary>
/// Converter used to support System.Text.Json serialization/deserialization of Crs (Coordinate Reference System).
/// Handles NamedCrs, LinkedCrs, and Unspecified CRS types.
/// Ensures output format matches Newtonsoft.Json exactly.
/// </summary>
internal sealed class CrsSTJConverter : JsonConverter<Crs>
{
public override bool HandleNull => true;

/// <summary>
/// Deserializes a CRS from JSON.
/// Supports named CRS (e.g., EPSG:4326) and linked CRS with optional type.
/// Returns Crs.Unspecified for null values.
/// </summary>
public override Crs Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
Comment thread
dibahlfi marked this conversation as resolved.
{
return Crs.Unspecified;
}

if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException(RMResources.JsonUnexpectedToken);
}

JsonElement rootElement = JsonDocument.ParseValue(ref reader).RootElement;
if (!rootElement.TryGetProperty(STJMetaDataFields.Properties, out JsonElement properties) || (properties.ValueKind != JsonValueKind.Object))
{
throw new JsonException(RMResources.SpatialFailedToDeserializeCrs);
}

if (!rootElement.TryGetProperty(STJMetaDataFields.Type, out JsonElement crsType) || crsType.ValueKind != JsonValueKind.String)
{
throw new JsonException(RMResources.SpatialFailedToDeserializeCrs);
}

switch (crsType.GetString())
{
case "name":
if (!properties.TryGetProperty(STJMetaDataFields.Name, out JsonElement crsName) || crsName.ValueKind != JsonValueKind.String)
{
throw new JsonException(RMResources.SpatialFailedToDeserializeCrs);
}
return new NamedCrs(crsName.GetString());

case "link":
if (!properties.TryGetProperty(STJMetaDataFields.Href, out JsonElement crsHref) || crsHref.ValueKind != JsonValueKind.String)
{
throw new JsonException(RMResources.SpatialFailedToDeserializeCrs);
}

if (properties.TryGetProperty(STJMetaDataFields.Type, out JsonElement crsHrefType))
{
if (crsHrefType.ValueKind != JsonValueKind.String)
{
throw new JsonException(RMResources.SpatialFailedToDeserializeCrs);
}
return new LinkedCrs(crsHref.GetString(), crsHrefType.GetString());
}
return new LinkedCrs(crsHref.GetString());

default:
throw new JsonException(RMResources.SpatialFailedToDeserializeCrs);
}

}
/// <summary>
/// Serializes a CRS to JSON.
/// Outputs different JSON structures based on CRS type (Named, Linked, or Unspecified).
/// </summary>
public override void Write(Utf8JsonWriter writer, Crs crs, JsonSerializerOptions options)
{
if (crs == null)
{
writer.WriteNullValue();
return;
}

switch (crs.Type)
{
case CrsType.Linked:
{
writer.WriteStartObject();
LinkedCrs linkedCrs = (LinkedCrs)crs;
writer.WriteString(STJMetaDataFields.Type, "link");
writer.WritePropertyName(STJMetaDataFields.Properties);
writer.WriteStartObject();
writer.WriteString(STJMetaDataFields.Href, linkedCrs.Href);
if (linkedCrs.HrefType != null)
{
writer.WriteString(STJMetaDataFields.Type, linkedCrs.HrefType);
}

writer.WriteEndObject();
writer.WriteEndObject();
break;
}
case CrsType.Named:
{
writer.WriteStartObject();
NamedCrs namedCrs = (NamedCrs)crs;
writer.WriteString(STJMetaDataFields.Type, "name");
writer.WritePropertyName(STJMetaDataFields.Properties);
writer.WriteStartObject();
writer.WriteString(STJMetaDataFields.Name, namedCrs.Name);
writer.WriteEndObject();
writer.WriteEndObject();
break;
}
case CrsType.Unspecified:
writer.WriteNullValue();
break;
}

}
}
}
Loading
Loading