我有一个需要反序列化的 json 字符串(在 WPF 应用程序中,使用 System.Net.Json)。树中的子对象(节点)包含可变数量的具有变量名称的属性/节点。 “最小”样本如下所示:
“间隔”:[{ “时间戳”:1677477728, “123456”:{ “子区间”:[{ “最大值”:“56.7”, “标签”:“Leq” }, { “最大”:“58.1”, “标签”:“Lmax” } ] } }, { “时间戳”:1677477730, “54321”:{ “子区间”:[{ “价值”:“58.5”, “标签”:“Leq” }, { “价值”:“59.5”, “标签”:“Lmax” } ] }, “56789”:{ “子区间”:[{ “价值”:“78.2”, “标签”:“Lmax” }, { “价值”:“74.3”, “标签”:“Leq” } ] } } ]
即一个带有“时间戳”的数组“间隔”和以数字字符串作为键的不同数量的对象/节点。
随着以下
public class IntervalMeta
{
public long? Timestamp { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement>? MeasurementPoints { get; set; } = new();
}
这给出了一个包含 JsonElements 的字典,我可以逐步查看它并查找所需的属性。如果有一个
就好了public Dictionary<string, SubInterval>? MeasurementPoints { get; set; } = new();
在哪里
SubInterval
:
public class SubInterval
{
public string? Max { get; set; }
public string? Label { get; set; }
}
我希望并尝试制作一个我可以使用的自定义 JsonConverter,但有许多我不知道如何处理的问题: 问题 0:如何让它使用自定义 JsonConverter?
我对转换器的尝试:
public class MeasurementPointDictionaryJsonConverter : JsonConverter<Dictionary<string, SubInterval>>
{
public override Dictionary<string, SubInterval>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var dict = new Dictionary<string, SubInterval>();
// Issue 3: How do loop over the contents in the Interval node (containing 0 or more SubIntervals)
while (reader.Read())
{
// Issue 1: How do I read the key?
var measurementPointId = reader.GetString();
// Issue 2: How do I deserialize the node to a SubInterval?
string value = reader.GetString();
var interval = JsonSerializer.Deserialize<SubInterval>(value, options);
dict.Add(measurementPointId ?? "", interval ?? new());
}
return dict;
}
public override void Write(Utf8JsonWriter writer, Dictionary<string, SubInterval> value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
我试过用以下方法装饰
MeasurementPoints
:
[JsonConverter(typeof(MeasurementPointDictionaryJsonConverter))]
public Dictionary<string, SubInterval>? MeasurementPoints { get; set; } = new();
但这只会导致
MeasurementPoints == null
。添加JsonExtensionData
属性:
[JsonExtensionData]
[JsonConverter(typeof(MeasurementPointDictionaryJsonConverter))]
public Dictionary<string, SubInterval>? MeasurementPoints { get; set; } = new();
尝试反序列化时抛出错误(似乎
JsonExtensionData
只能处理Dictionary任何帮助将不胜感激(我问过 chatgtp 但我没有给我更多 :))。
我想出了这样的东西。
但在此之前,我想指出,在您的字典中,您没有单数 SubInterval,而是 SubInterval 的集合。如果我错了,请纠正我。
转换器:
public class CustomConverter : JsonConverter<List<IntervalMeta>>
{
public override List<IntervalMeta> Read(ref Utf8JsonReader reader, Type typeToConvert,
JsonSerializerOptions options)
{
using var jsonDocument = JsonDocument.ParseValue(ref reader);
var root = jsonDocument.RootElement;
var intervals = root.GetProperty("intervals").EnumerateArray();
var values = new List<IntervalMeta>();
foreach (var interval in intervals)
{
var item = new IntervalMeta();
foreach (var property in interval.EnumerateObject())
{
if (property.Name == "timestamp")
{
if (property.Value.TryGetInt64(out var value))
{
item.Timestamp = value;
}
continue;
}
Dictionary<string, SubInterval[]> subIntervalDict =
JsonSerializer.Deserialize<Dictionary<string, SubInterval[]>>(
property.Value.GetRawText(), options);
item.MeasurementPoints = subIntervalDict;
}
values.Add(item);
}
return values;
}
public override void Write(Utf8JsonWriter writer, List<IntervalMeta> value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
我用于测试的其余代码:
public class IntervalMeta
{
public long? Timestamp { get; set; }
public Dictionary<string, SubInterval[]> MeasurementPoints { get; set; } = new();
}
public class SubInterval
{
public string Max { get; set; }
public string Label { get; set; }
}
class Program
{
static async Task Main(string[] args)
{
var input = @"
{
""intervals"":[
{
""timestamp"":1677477728,
""123456"":{
""subintervals"":[
{
""max"":""56.7"",
""label"":""Leq""
},
{
""max"":""58.1"",
""label"":""Lmax""
}
]
}
},
{
""timestamp"":1677477730,
""54321"":{
""subintervals"":[
{
""value"":""58.5"",
""label"":""Leq""
},
{
""value"":""59.5"",
""label"":""Lmax""
}
]
},
""56789"":{
""subintervals"":[
{
""value"":""78.2"",
""label"":""Lmax""
},
{
""value"":""74.3"",
""label"":""Leq""
}
]
}
}
]
}";
var test = JsonSerializer.Deserialize<List<IntervalMeta>>(input, new JsonSerializerOptions
{
Converters = { new CustomConverter() },
PropertyNameCaseInsensitive = true
});
Console.WriteLine(test);
}