我正在嘗試反序列化由外部 REST API 提供的非常丑陋的 JSON,并且想知道“正確”的方式來做到這一點(我在 .net 6 中使用 System.Text.Json)。詳情如下:
我有一個資料模型:
class DeviceData{
//lots of properties
}
在為單個實體進行 API 查詢時,它作業正常(即我可以只是JsonSerializer.Deserialize<DeviceData>回應),因為它回傳一個好的 JSON 期望:
{
"property1_name": value,
"property2_name": value,
...
}
當我使用 API 提供的批處理查詢時,問題就開始了,因為api_url/batch?=device1,device2,...看起來好像有人未能創建陣列(設備 1 是從資料庫中提取的字母數字字串)的回應是:
{
"names":[
"device1",
"device2",
...
],
"device1":{
"stuff_i_dont_need": value,
"device1": {
"property1_name": value,
"property2_name": value,
...
}
}
"device2":{
...
}
...
}
動態屬性名稱的雙重嵌套意味著我不能將第二個回應反序列化為對的字典<string, myclass>。我設法使用 JsonDocument 一起破解了一些東西,但它非常難看,感覺應該有一個很好的簡短方法來做到這一點,只需要 JsonSerializer 和一些讀者覆寫。
uj5u.com熱心網友回復:
使用如何在 System.Text.Json 中使用 JSON 檔案、Utf8JsonReader 和 Utf8JsonWriter作為模板中的 JSON 有效負載的反序列化子部分,您可以執行以下操作:
JsonNode root = JsonNode.Parse(json)!;
Dictionary<string, X> devices = new();
foreach(string name in root["names"]!.AsArray()) {
var o = root[name][name].AsObject();
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream);
o.WriteTo(writer);
writer.Flush();
X? x = JsonSerializer.Deserialize<X>(stream.ToArray());
var innerJson = root[name][name].ToJsonString();
devices[name] = x;
}
foreach(var d in devices) Console.WriteLine($"{d.Key}: {d.Value}");
這列印
device1: X { property1_name = 12, property2_name = 13 }
device2: X { property1_name = 22, property2_name = 23 }
我不確定這是否比呼叫更快/更好ToJsonString():
JsonNode root = JsonNode.Parse(json)!;
Dictionary<string, X> devices = new();
foreach(string name in root["names"]!.AsArray()) {
var innerJson = root[name][name].ToJsonString();
devices[name] = JsonSerializer.Deserialize<X>(innerJson);
}
foreach(var d in devices) Console.WriteLine($"{d.Key}: {d.Value}")
如果您喜歡,您可以使用完整的 LINQ:
JsonNode root = JsonNode.Parse(json)!;
Dictionary<string, X> devices = root["names"]!.AsArray()
.Select(name => (string)name)
.ToDictionary(
keySelector: name => name,
elementSelector: name => System.Text.Json.JsonSerializer.Deserialize<X>(root[name][name].ToJsonString()));
foreach(var d in devices) Console.WriteLine($"{d.Key}: {d.Value}");
兩者都列印
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/437617.html
