using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; namespace Cepis; /// /// Reads the geo block, yielding for anything it /// cannot make sense of. /// /// /// A malformed coordinate is not worth losing the whole address over: the rest /// of the response is still useful, and an address with no coordinate is a /// shape callers already handle, since about 43% of CEPs have none. /// internal sealed class GeoConverter : JsonConverter { public override Geo? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using var document = JsonDocument.ParseValue(ref reader); var root = document.RootElement; if (root.ValueKind != JsonValueKind.Object) { return null; } var lat = ReadDouble(root, "lat"); var lon = ReadDouble(root, "lon"); var raio = ReadDouble(root, "raio_m"); var precisao = ReadString(root, "precisao"); if (lat is null || lon is null || raio is null || precisao is null) { return null; } return new Geo { Lat = lat.Value, Lon = lon.Value, RaioM = (int)Math.Round(raio.Value), Precisao = precisao, }; } public override void Write(Utf8JsonWriter writer, Geo? value, JsonSerializerOptions options) { ArgumentNullException.ThrowIfNull(writer); if (value is null) { writer.WriteNullValue(); return; } writer.WriteStartObject(); writer.WriteNumber("lat", value.Lat); writer.WriteNumber("lon", value.Lon); writer.WriteNumber("raio_m", value.RaioM); writer.WriteString("precisao", value.Precisao); writer.WriteEndObject(); } private static double? ReadDouble(JsonElement owner, string name) { if (!owner.TryGetProperty(name, out var element)) { return null; } return element.ValueKind switch { JsonValueKind.Number => element.TryGetDouble(out var number) ? number : null, JsonValueKind.String => double.TryParse( element.GetString(), NumberStyles.Float, CultureInfo.InvariantCulture, out var parsed) ? parsed : null, _ => null, }; } private static string? ReadString(JsonElement owner, string name) => owner.TryGetProperty(name, out var element) && element.ValueKind == JsonValueKind.String ? element.GetString() : null; }