Skip to content

Commit e0bc423

Browse files
authored
Add converter to make sure we have a string value when expect it (#1126)
* Add converter to make sure we have a string value when expect it * Fixed comment
1 parent 7f9914e commit e0bc423

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
2+
namespace NetDaemon.HassClient.Tests.Json;
3+
4+
public class EnsureStringConverterTests
5+
{
6+
/// <summary>
7+
/// Default Json serialization options, Hass expects intended
8+
/// </summary>
9+
private readonly JsonSerializerOptions _defaultSerializerOptions = new()
10+
{
11+
WriteIndented = false,
12+
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
13+
};
14+
15+
[Fact]
16+
public void TestConvertAValidString()
17+
{
18+
const string jsonDevice = @"
19+
{
20+
""config_entries"": [],
21+
""connections"": [],
22+
""manufacturer"": ""Google Inc."",
23+
""model"": 123123,
24+
""name"": 123,
25+
""serial_number"": ""1.0"",
26+
""sw_version"": ""100"",
27+
""hw_version"": null,
28+
""id"": ""42cdda32a2a3428e86c2e27699d79ead"",
29+
""via_device_id"": null,
30+
""area_id"": null,
31+
""name_by_user"": null
32+
}
33+
";
34+
var hassDevice = JsonSerializer.Deserialize<HassDevice>(jsonDevice, _defaultSerializerOptions);
35+
hassDevice!.SerialNumber.Should().Be("1.0");
36+
hassDevice!.SoftwareVersion.Should().Be("100");
37+
hassDevice!.HardwareVersion.Should().BeNull();
38+
}
39+
40+
[Fact]
41+
public void TestConverAInvalidString()
42+
{
43+
const string jsonDevice = @"
44+
{
45+
""config_entries"": [],
46+
""connections"": [],
47+
""model"": ""Chromecast"",
48+
""serial_number"": [""1.0"", ""2.0""],
49+
""name"": ""My TV"",
50+
""sw_version"": { ""attribute"": ""1.0"" },
51+
""manufacturer"": ""Google Inc."",
52+
""hw_version"": 100,
53+
""id"": ""42cdda32a2a3428e86c2e27699d79ead"",
54+
""via_device_id"": null,
55+
""area_id"": null,
56+
""name_by_user"": null
57+
}
58+
";
59+
var hassDevice = JsonSerializer.Deserialize<HassDevice>(jsonDevice, _defaultSerializerOptions);
60+
hassDevice!.SerialNumber.Should().BeNull();
61+
hassDevice!.SoftwareVersion.Should().BeNull();
62+
hassDevice!.HardwareVersion.Should().BeNull();
63+
64+
// Make sure it is skipped correctly by checking the next property is read
65+
hassDevice!.Manufacturer.Should().Be("Google Inc.");
66+
hassDevice!.Id.Should().Be("42cdda32a2a3428e86c2e27699d79ead");
67+
hassDevice!.Name.Should().Be("My TV");
68+
}
69+
}

src/Client/NetDaemon.HassClient/Common/HomeAssistant/Model/HassDevice.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ public record HassDevice
2222
#pragma warning disable CA1056 // It's ok for this URL to be a string
2323
[JsonPropertyName("configuration_url")] public string? ConfigurationUrl { get; init; }
2424
#pragma warning restore CA1056
25+
[JsonConverter(typeof(EnsureStringConverter))]
2526
[JsonPropertyName("hw_version")] public string? HardwareVersion { get; init; }
27+
[JsonConverter(typeof(EnsureStringConverter))]
2628
[JsonPropertyName("sw_version")] public string? SoftwareVersion { get; init; }
29+
[JsonConverter(typeof(EnsureStringConverter))]
2730
[JsonPropertyName("serial_number")] public string? SerialNumber { get; init; }
2831
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Diagnostics;
2+
3+
namespace NetDaemon.Client.Internal.Json;
4+
5+
/// <summary>
6+
/// Converts a Json element that can be a string or returns null if it is not a string
7+
/// </summary>
8+
class EnsureStringConverter : JsonConverter<string?>
9+
{
10+
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
11+
{
12+
if (reader.TokenType == JsonTokenType.String)
13+
{
14+
return reader.GetString() ?? throw new UnreachableException("Token is expected to be a string");
15+
}
16+
17+
// Skip the children of current token
18+
reader.Skip();
19+
return null;
20+
}
21+
22+
public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options) => throw new NotSupportedException();
23+
}

0 commit comments

Comments
 (0)