Skip to content

Add deserialization support for GeoBounds and GeoLocation #8586

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -79,24 +79,24 @@ public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? prov
}

internal sealed class UsernameConverter :
JsonConverter<Name>
JsonConverter<Username>
{
public override Name? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
public override Username? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
reader.ValidateToken(JsonTokenType.String);

return reader.GetString()!;
}

public override Name ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert,
public override Username ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert,
JsonSerializerOptions options)
{
reader.ValidateToken(JsonTokenType.PropertyName);

return reader.GetString()!;
}

public override void Write(Utf8JsonWriter writer, Name value, JsonSerializerOptions options)
public override void Write(Utf8JsonWriter writer, Username value, JsonSerializerOptions options)
{
if (value?.Value is null)
{
Expand All @@ -106,7 +106,7 @@ public override void Write(Utf8JsonWriter writer, Name value, JsonSerializerOpti
writer.WriteStringValue(value.Value);
}

public override void WriteAsPropertyName(Utf8JsonWriter writer, Name value, JsonSerializerOptions options)
public override void WriteAsPropertyName(Utf8JsonWriter writer, Username value, JsonSerializerOptions options)
{
if (value?.Value is null)
{
Expand Down
63 changes: 62 additions & 1 deletion src/Elastic.Clients.Elasticsearch/_Shared/Types/GeoBounds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,70 @@ public sealed partial class GeoBounds
internal sealed class GeoBoundsConverter :
JsonConverter<GeoBounds>
{
// Coordinates.

private static readonly JsonEncodedText PropBottom = JsonEncodedText.Encode("bottom");
private static readonly JsonEncodedText PropLeft = JsonEncodedText.Encode("left");
private static readonly JsonEncodedText PropRight = JsonEncodedText.Encode("right");
private static readonly JsonEncodedText PropTop = JsonEncodedText.Encode("top");

// TopLeftBottomRight.

private static readonly JsonEncodedText PropBottomRight = JsonEncodedText.Encode("bottom_right");
private static readonly JsonEncodedText PropTopLeft = JsonEncodedText.Encode("top_left");

// TopRightBottomLeft.

private static readonly JsonEncodedText PropBottomLeft = JsonEncodedText.Encode("bottom_left");
private static readonly JsonEncodedText PropTopRight = JsonEncodedText.Encode("top_right");

// WKT.

private static readonly JsonEncodedText PropWkt = JsonEncodedText.Encode("wkt");

public override GeoBounds? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new InvalidOperationException();
reader.ValidateToken(JsonTokenType.StartObject);

var readerSnapshot = reader;
reader.Read();

GeoBounds.Kind? kind = null;
if (reader.TokenType is JsonTokenType.PropertyName)
{
if (reader.ValueTextEquals(PropBottom) || reader.ValueTextEquals(PropLeft) ||
reader.ValueTextEquals(PropRight) || reader.ValueTextEquals(PropTop))
{
kind = GeoBounds.Kind.Coordinates;
}

if (reader.ValueTextEquals(PropBottomRight) || reader.ValueTextEquals(PropTopLeft))
{
kind = GeoBounds.Kind.TopLeftBottomRight;
}

if (reader.ValueTextEquals(PropBottomLeft) || reader.ValueTextEquals(PropTopRight))
{
kind = GeoBounds.Kind.TopRightBottomLeft;
}

if (reader.ValueTextEquals(PropWkt))
{
kind = GeoBounds.Kind.Wkt;
}
}

reader = readerSnapshot;

return kind switch
{
GeoBounds.Kind.Coordinates => new(reader.ReadValue<CoordsGeoBounds>(options)),
GeoBounds.Kind.TopLeftBottomRight => new(reader.ReadValue<TopLeftBottomRightGeoBounds>(options)),
GeoBounds.Kind.TopRightBottomLeft => new(reader.ReadValue<TopRightBottomLeftGeoBounds>(options)),
GeoBounds.Kind.Wkt => new(reader.ReadValue<WktGeoBounds>(options)),
null => throw new JsonException($"Unrecognized '{typeof(GeoBounds)}' variant."),
_ => throw new InvalidOperationException("unreachable")
};
}

public override void Write(Utf8JsonWriter writer, GeoBounds value, JsonSerializerOptions options)
Expand Down
51 changes: 50 additions & 1 deletion src/Elastic.Clients.Elasticsearch/_Shared/Types/GeoLocation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,58 @@ public partial class GeoLocation
internal sealed class GeoLocationConverter :
JsonConverter<GeoLocation>
{
// LatitudeLongitude.

private static readonly JsonEncodedText PropLat = JsonEncodedText.Encode("lat");
private static readonly JsonEncodedText PropLon = JsonEncodedText.Encode("lon");

// GeoHash.

private static readonly JsonEncodedText PropGeoHash = JsonEncodedText.Encode("geohash");

public override GeoLocation? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new InvalidOperationException();
if (reader.TokenType is JsonTokenType.String)
{
return new GeoLocation(reader.GetString()!);
}

if (reader.TokenType is JsonTokenType.StartArray)
{
return new GeoLocation(reader.ReadCollectionValue<double>(options, null)!);
}

if (reader.TokenType is JsonTokenType.StartObject)
{
var readerSnapshot = reader;
reader.Read();

GeoLocation.Kind? kind = null;
if (reader.TokenType is JsonTokenType.PropertyName)
{
if (reader.ValueTextEquals(PropLat) || reader.ValueTextEquals(PropLon))
{
kind = GeoLocation.Kind.LatitudeLongitude;
}

if (reader.ValueTextEquals(PropGeoHash))
{
kind = GeoLocation.Kind.GeoHash;
}
}

reader = readerSnapshot;

return kind switch
{
GeoLocation.Kind.LatitudeLongitude => new(reader.ReadValue<LatLonGeoLocation>(options)),
GeoLocation.Kind.GeoHash => new(reader.ReadValue<GeoHashLocation>(options)),
null => throw new JsonException($"Unrecognized '{typeof(GeoLocation)}' variant."),
_ => throw new InvalidOperationException("unreachable")
};
}

throw new JsonException($"Unrecognized '{typeof(GeoLocation)}' variant.");
}

public override void Write(Utf8JsonWriter writer, GeoLocation value, JsonSerializerOptions options)
Expand Down
Loading