Skip to content

Commit 5069f2b

Browse files
Handle numeric manufacturer on HassDevice Deserialization (#1348)
1 parent 89da80a commit 5069f2b

File tree

7 files changed

+185
-64
lines changed

7 files changed

+185
-64
lines changed

src/Client/NetDaemon.HassClient.Tests/Json/HassDeviceConverterTests.cs

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,41 +14,58 @@ public class JsonConverterTests
1414
[Fact]
1515
public void TestConversionWithNumericValue()
1616
{
17-
const string jsonDevice = @"
17+
const string jsonDevice = """
1818
{
19-
""config_entries"": [],
20-
""connections"": [],
21-
""manufacturer"": ""Google Inc."",
22-
""model"": 123123,
23-
""name"": 123,
24-
""sw_version"": null,
25-
""id"": ""42cdda32a2a3428e86c2e27699d79ead"",
26-
""via_device_id"": null,
27-
""area_id"": null,
28-
""name_by_user"": null
19+
"config_entries": [],
20+
"connections": [],
21+
"manufacturer": 1,
22+
"model": 123123,
23+
"name": 123,
24+
"sw_version": null,
25+
"id": "42cdda32a2a3428e86c2e27699d79ead",
26+
"via_device_id": null,
27+
"area_id": null,
28+
"name_by_user": null,
29+
"labels": ["label1", 123]
2930
}
30-
";
31+
""";
3132
var hassDevice = JsonSerializer.Deserialize<HassDevice>(jsonDevice, _defaultSerializerOptions);
3233
hassDevice!.Model.Should().Be("123123");
34+
hassDevice!.Manufacturer.Should().Be("1");
35+
hassDevice!.Name.Should().Be("123");
36+
hassDevice!.Labels.Should().BeEquivalentTo(["label1", "123"]);
37+
}
38+
39+
[Fact]
40+
public void TestConversionWithLabelsSingleValue()
41+
{
42+
const string jsonDevice = """
43+
{
44+
"labels": 123
45+
}
46+
""";
47+
var hassDevice = JsonSerializer.Deserialize<HassDevice>(jsonDevice, _defaultSerializerOptions);
48+
49+
hassDevice!.Labels.Should().BeEquivalentTo(["123"]);
3350
}
3451

3552
[Fact]
3653
public void TestConversionWithStringValue()
3754
{
38-
const string jsonDevice = @"
39-
{
40-
""config_entries"": [],
41-
""connections"": [],
42-
""manufacturer"": ""Google Inc."",
43-
""model"": ""Chromecast"",
44-
""name"": ""My TV"",
45-
""sw_version"": null,
46-
""id"": ""42cdda32a2a3428e86c2e27699d79ead"",
47-
""via_device_id"": null,
48-
""area_id"": null,
49-
""name_by_user"": null
50-
}
51-
";
55+
const string jsonDevice = """
56+
{
57+
"config_entries": [],
58+
"connections": [],
59+
"manufacturer": "Google Inc.",
60+
"model": "Chromecast",
61+
"name": "My TV",
62+
"sw_version": null,
63+
"id": "42cdda32a2a3428e86c2e27699d79ead",
64+
"via_device_id": null,
65+
"area_id": null,
66+
"name_by_user": null
67+
}
68+
""";
5269
var hassDevice = JsonSerializer.Deserialize<HassDevice>(jsonDevice, _defaultSerializerOptions);
5370
hassDevice!.Model.Should().Be("Chromecast");
5471
}

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

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,23 @@
22

33
public record HassArea
44
{
5-
[JsonPropertyName("name")] public string? Name { get; init; }
6-
[JsonPropertyName("area_id")] public string? Id { get; init; }
5+
[JsonConverter(typeof(EnsureStringConverter))]
6+
[JsonPropertyName("name")]
7+
public string? Name { get; init; }
78

8-
[JsonPropertyName("labels")] public IReadOnlyList<string> Labels { get; init; } = [];
9+
[JsonConverter(typeof(EnsureStringConverter))]
10+
[JsonPropertyName("area_id")]
11+
public string? Id { get; init; }
912

10-
[JsonPropertyName("floor_id")] public string? FloorId { get; init; }
13+
[JsonConverter(typeof(EnsureArrayOfStringConverter))]
14+
[JsonPropertyName("labels")]
15+
public IReadOnlyList<string> Labels { get; init; } = [];
1116

12-
[JsonPropertyName("icon")] public string? Icon { get; init; }
17+
[JsonConverter(typeof(EnsureStringConverter))]
18+
[JsonPropertyName("floor_id")]
19+
public string? FloorId { get; init; }
20+
21+
[JsonConverter(typeof(EnsureStringConverter))]
22+
[JsonPropertyName("icon")]
23+
public string? Icon { get; init; }
1324
}

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

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,53 @@
22

33
public record HassDevice
44
{
5-
[JsonPropertyName("manufacturer")] public string? Manufacturer { get; init; }
5+
[JsonConverter(typeof(EnsureStringConverter))]
6+
[JsonPropertyName("manufacturer")]
7+
public string? Manufacturer { get; init; }
68

7-
[JsonPropertyName("model")]
89
[JsonConverter(typeof(EnsureStringConverter))]
10+
[JsonPropertyName("model")]
911
public string? Model { get; init; }
1012

11-
[JsonPropertyName("id")] public string? Id { get; init; }
13+
[JsonPropertyName("id")]
14+
[JsonConverter(typeof(EnsureStringConverter))]
15+
public string? Id { get; init; }
1216

13-
[JsonPropertyName("area_id")] public string? AreaId { get; init; }
17+
[JsonPropertyName("area_id")]
1418
[JsonConverter(typeof(EnsureStringConverter))]
15-
[JsonPropertyName("name")] public string? Name { get; init; }
19+
public string? AreaId { get; init; }
1620

17-
[JsonPropertyName("name_by_user")] public string? NameByUser { get; init; }
21+
[JsonConverter(typeof(EnsureStringConverter))]
22+
[JsonPropertyName("name")]
23+
public string? Name { get; init; }
1824

19-
[JsonPropertyName("labels")] public IReadOnlyList<string> Labels { get; init; } = [];
25+
[JsonConverter(typeof(EnsureStringConverter))]
26+
[JsonPropertyName("name_by_user")]
27+
public string? NameByUser { get; init; }
2028

21-
#pragma warning disable CA1056 // It's ok for this URL to be a string
22-
[JsonPropertyName("configuration_url")] public string? ConfigurationUrl { get; init; }
23-
#pragma warning restore CA1056
29+
[JsonConverter(typeof(EnsureArrayOfStringConverter))]
30+
[JsonPropertyName("labels")]
31+
public IReadOnlyList<string> Labels { get; init; } = [];
32+
33+
#pragma warning disable CA1056 // It's ok for this URL to be a string
2434
[JsonConverter(typeof(EnsureStringConverter))]
25-
[JsonPropertyName("hw_version")] public string? HardwareVersion { get; init; }
35+
[JsonPropertyName("configuration_url")]
36+
public string? ConfigurationUrl { get; init; }
37+
#pragma warning restore CA1056
38+
2639
[JsonConverter(typeof(EnsureStringConverter))]
27-
[JsonPropertyName("sw_version")] public string? SoftwareVersion { get; init; }
40+
[JsonPropertyName("hw_version")]
41+
public string? HardwareVersion { get; init; }
42+
43+
[JsonConverter(typeof(EnsureStringConverter))]
44+
[JsonPropertyName("sw_version")]
45+
public string? SoftwareVersion { get; init; }
46+
2847
[JsonConverter(typeof(EnsureStringConverter))]
29-
[JsonPropertyName("serial_number")] public string? SerialNumber { get; init; }
48+
[JsonPropertyName("serial_number")]
49+
public string? SerialNumber { get; init; }
3050

3151
[JsonConverter(typeof(EnsureArrayOfArrayOfStringConverter))]
32-
[JsonPropertyName("identifiers")] public IReadOnlyList<IReadOnlyList<string>> Identifiers { get; init; } = [];
52+
[JsonPropertyName("identifiers")]
53+
public IReadOnlyList<IReadOnlyList<string>> Identifiers { get; init; } = [];
3354
}

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

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,34 @@
22

33
public record HassEntity
44
{
5-
[JsonPropertyName("device_id")] public string? DeviceId { get; init; }
5+
[JsonConverter(typeof(EnsureStringConverter))]
6+
[JsonPropertyName("device_id")]
7+
public string? DeviceId { get; init; }
68

7-
[JsonPropertyName("entity_id")] public string? EntityId { get; init; }
9+
[JsonConverter(typeof(EnsureStringConverter))]
10+
[JsonPropertyName("entity_id")]
11+
public string? EntityId { get; init; }
812

9-
[JsonPropertyName("area_id")] public string? AreaId { get; init; }
13+
[JsonConverter(typeof(EnsureStringConverter))]
14+
[JsonPropertyName("area_id")]
15+
public string? AreaId { get; init; }
1016

11-
[JsonPropertyName("name")] public string? Name { get; init; }
17+
[JsonConverter(typeof(EnsureStringConverter))]
18+
[JsonPropertyName("name")]
19+
public string? Name { get; init; }
1220

13-
[JsonPropertyName("icon")] public string? Icon { get; init; }
21+
[JsonConverter(typeof(EnsureStringConverter))]
22+
[JsonPropertyName("icon")]
23+
public string? Icon { get; init; }
1424

15-
[JsonPropertyName("platform")] public string? Platform { get; init; }
25+
[JsonConverter(typeof(EnsureStringConverter))]
26+
[JsonPropertyName("platform")]
27+
public string? Platform { get; init; }
1628

17-
[JsonPropertyName("labels")] public IReadOnlyList<string> Labels { get; init; } = [];
18-
19-
[JsonPropertyName("options")]public HassEntityOptions? Options { get; init; }
20-
}
29+
[JsonConverter(typeof(EnsureArrayOfStringConverter))]
30+
[JsonPropertyName("labels")]
31+
public IReadOnlyList<string> Labels { get; init; } = [];
2132

33+
[JsonPropertyName("options")]
34+
public HassEntityOptions? Options { get; init; }
35+
}

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@
22

33
public record HassFloor
44
{
5-
[JsonPropertyName("level")] public short? Level { get; init; }
5+
[JsonPropertyName("level")]
6+
public short? Level { get; init; }
67

7-
[JsonPropertyName("icon")] public string? Icon { get; init; }
8+
[JsonConverter(typeof(EnsureStringConverter))]
9+
[JsonPropertyName("icon")]
10+
public string? Icon { get; init; }
811

9-
[JsonPropertyName("floor_id")] public string? Id { get; init; }
12+
[JsonConverter(typeof(EnsureStringConverter))]
13+
[JsonPropertyName("floor_id")]
14+
public string? Id { get; init; }
1015

11-
[JsonPropertyName("name")] public string? Name { get; init; }
16+
[JsonConverter(typeof(EnsureStringConverter))]
17+
[JsonPropertyName("name")]
18+
public string? Name { get; init; }
1219
}

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,23 @@ namespace NetDaemon.Client.HomeAssistant.Model;
22

33
public record HassLabel
44
{
5-
[JsonPropertyName("color")] public string? Color { get; init; }
5+
[JsonConverter(typeof(EnsureStringConverter))]
6+
[JsonPropertyName("color")]
7+
public string? Color { get; init; }
68

7-
[JsonPropertyName("description")] public string? Description { get; init; }
9+
[JsonConverter(typeof(EnsureStringConverter))]
10+
[JsonPropertyName("description")]
11+
public string? Description { get; init; }
812

9-
[JsonPropertyName("icon")] public string? Icon { get; init; }
13+
[JsonConverter(typeof(EnsureStringConverter))]
14+
[JsonPropertyName("icon")]
15+
public string? Icon { get; init; }
1016

11-
[JsonPropertyName("label_id")] public string? Id { get; init; }
17+
[JsonConverter(typeof(EnsureStringConverter))]
18+
[JsonPropertyName("label_id")]
19+
public string? Id { get; init; }
1220

13-
[JsonPropertyName("name")] public string? Name { get; init; }
21+
[JsonConverter(typeof(EnsureStringConverter))]
22+
[JsonPropertyName("name")]
23+
public string? Name { get; init; }
1424
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
namespace NetDaemon.Client.Internal.Json;
2+
3+
class EnsureArrayOfStringConverter : JsonConverter<IReadOnlyList<string>>
4+
{
5+
private readonly EnsureStringConverter _ensureStringConverter = new();
6+
7+
public override IReadOnlyList<string> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
8+
{
9+
if (reader.TokenType == JsonTokenType.StartArray)
10+
{
11+
var list = new List<string>();
12+
while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
13+
{
14+
string? item = _ensureStringConverter.Read(ref reader, typeof(string), options);
15+
if (item != null)
16+
{
17+
list.Add(item);
18+
}
19+
}
20+
return list;
21+
}
22+
23+
string? singleItem = _ensureStringConverter.Read(ref reader, typeof(string), options);
24+
if (singleItem != null)
25+
{
26+
return new List<string> { singleItem };
27+
}
28+
29+
return [];
30+
}
31+
32+
public override void Write(Utf8JsonWriter writer, IReadOnlyList<string> value, JsonSerializerOptions options)
33+
{
34+
writer.WriteStartArray();
35+
foreach (var item in value)
36+
{
37+
writer.WriteStringValue(item);
38+
}
39+
writer.WriteEndArray();
40+
}
41+
}

0 commit comments

Comments
 (0)