Skip to content

Commit 7a9def4

Browse files
Fix crash in 2025.5 (#1309)
* Add test * Add converter for arrays of arrays of strings, more test cases * Remove testing workaroudn --------- Co-authored-by: Frank Bakker <[email protected]> Co-authored-by: Frank Bakker <[email protected]>
1 parent dc49458 commit 7a9def4

File tree

4 files changed

+74
-4
lines changed

4 files changed

+74
-4
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@ public record HassDevice
2828
[JsonConverter(typeof(EnsureStringConverter))]
2929
[JsonPropertyName("serial_number")] public string? SerialNumber { get; init; }
3030

31+
[JsonConverter(typeof(EnsureArrayOfArrayOfStringConverter))]
3132
[JsonPropertyName("identifiers")] public IReadOnlyList<IReadOnlyList<string>> Identifiers { get; init; } = [];
3233
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
namespace NetDaemon.Client.Internal.Json;
2+
3+
using System.Text.Json;
4+
using System.Text.Json.Serialization;
5+
6+
/// <summary>
7+
/// Converts a Json element that can be an array of arrays of strings to a list of lists of strings.
8+
/// </summary>
9+
class EnsureArrayOfArrayOfStringConverter : JsonConverter<IReadOnlyList<IReadOnlyList<string>>>
10+
{
11+
private readonly EnsureStringConverter _ensureStringConverter = new();
12+
13+
public override IReadOnlyList<IReadOnlyList<string>> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
14+
{
15+
if (reader.TokenType == JsonTokenType.StartArray)
16+
{
17+
var list = new List<IReadOnlyList<string>>();
18+
while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
19+
{
20+
if (reader.TokenType == JsonTokenType.StartArray)
21+
{
22+
var innerList = new List<string>();
23+
while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
24+
{
25+
string? item = _ensureStringConverter.Read(ref reader, typeof(string), options);
26+
if (item != null)
27+
{
28+
innerList.Add(item);
29+
}
30+
}
31+
list.Add(innerList);
32+
}
33+
}
34+
return list;
35+
}
36+
37+
reader.Skip();
38+
return [];
39+
}
40+
41+
public override void Write(Utf8JsonWriter writer, IReadOnlyList<IReadOnlyList<string>> value, JsonSerializerOptions options)
42+
{
43+
writer.WriteStartArray();
44+
foreach (var innerList in value)
45+
{
46+
writer.WriteStartArray();
47+
foreach (var item in innerList)
48+
{
49+
writer.WriteStringValue(item);
50+
}
51+
writer.WriteEndArray();
52+
}
53+
writer.WriteEndArray();
54+
}
55+
}

src/Client/NetDaemon.HassClient/Internal/Json/EnsureStringConverter.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class EnsureStringConverter : JsonConverter<string?>
2020
if (reader.TryGetDouble(out var doubleValue))
2121
return doubleValue.ToString(CultureInfo.InvariantCulture);
2222

23+
reader.Skip();
2324
return null;
2425

2526
default:

src/HassModel/NetDaemon.HassModel.Tests/Internal/HassObjectMapperTest.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System.Text.Json;
22
using System.Text.Json.Serialization;
33
using NetDaemon.Client.HomeAssistant.Model;
4-
using NetDaemon.HassModel.Entities;
4+
using NetDaemon.Client.Internal.Json;
55
using NetDaemon.HassModel.Internal;
66

77
namespace NetDaemon.HassModel.Tests.Internal;
@@ -14,7 +14,7 @@ public class HassObjectMapperTest
1414
private readonly JsonSerializerOptions _defaultSerializerOptions = new()
1515
{
1616
WriteIndented = false,
17-
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
17+
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
1818
};
1919

2020
[Fact]
@@ -39,7 +39,10 @@ public void TestConversionWithIdentifiers()
3939
],
4040
[
4141
"SKIP"
42-
]
42+
],
43+
[1,2],
44+
[1.1, 2],
45+
["1", 2.2]
4346
]
4447
}
4548
""";
@@ -50,8 +53,18 @@ public void TestConversionWithIdentifiers()
5053

5154
var ndDevice = hassDevice.Map(Mock.Of<IHaRegistryNavigator>());
5255

53-
Assert.Single(ndDevice.Identifiers!);
56+
Assert.Equal(4, ndDevice.Identifiers!.Count);
5457
Assert.Equal(ndDevice.Identifiers![0].Item1, "Google");
5558
Assert.Equal(ndDevice.Identifiers![0].Item2, "42cdda32a2a3428e86c2e27699d79ead");
59+
60+
Assert.Equal(ndDevice.Identifiers![1].Item1, "1");
61+
Assert.Equal(ndDevice.Identifiers![1].Item2, "2");
62+
63+
Assert.Equal(ndDevice.Identifiers![2].Item1, "1.1");
64+
Assert.Equal(ndDevice.Identifiers![2].Item2, "2");
65+
66+
Assert.Equal(ndDevice.Identifiers![3].Item1, "1");
67+
Assert.Equal(ndDevice.Identifiers![3].Item2, "2.2");
5668
}
69+
5770
}

0 commit comments

Comments
 (0)