I have a json string that I need to deserialize (in a WPF app, using System.Net.Json). A subobject (node) in the tree contains a variable number of propertiers/nodes with variable names.
A "minimal" sample looks like this:
"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"
}
] }
} ]
I.e. a an array "intervals" with a "timestamp" and a varying number of objects/nodes that has a number-string as key.
With the following
public class IntervalMeta
{
public long? Timestamp { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement>? MeasurementPoints { get; set; } = new();
}
that gives a dictionary with JsonElements that I can step through and look for the desired properties. It would though be nice with a
public Dictionary<string, SubInterval[]>? MeasurementPoints { get; set; } = new();
where SubInterval
:
public class SubInterval
{
public string? Max { get; set; }
public string? Label { get; set; }
}
I am hoping and trying to make a custom JsonConverter that I could use but there are a number of issues that I don’t know how to handle:
Issue 0: how do I get it to use the custom JsonConverter?
My try for a converter:
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 intervals = JsonSerializer.Deserialize<SubInterval[]>(value, options);
dict.Add(measurementPointId ?? "", intervals ?? new());
}
return dict;
}
public override void Write(Utf8JsonWriter writer, Dictionary<string, SubInterval[]> value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
I have tried just decorating the MeasurementPoints
with:
[JsonConverter(typeof(MeasurementPointDictionaryJsonConverter))]
public Dictionary<string, SubInterval[]>? MeasurementPoints { get; set; } = new();
but that just result in MeasurementPoints == null
. Adding the JsonExtensionData
attribute:
[JsonExtensionData]
[JsonConverter(typeof(MeasurementPointDictionaryJsonConverter))]
public Dictionary<string, SubInterval[]>? MeasurementPoints { get; set; } = new();
Throws an error when trying to deserialize (seems that the JsonExtensionData
can only handle Dictionary<string, JsonElement> or Dictionary<string,object>).
Any help would be most appreciated (I have asked chatgtp but I didn’t give me much more 🙂 ).
EDIT: Corrected SubInterval => SubIntervals[]. Kudos to @KJanec
2
Answers
I come up with something like this.
But before that I want to note that in your dictionary you don’t have singular SubInterval but collection of SubInterval. Correct me if I’m wrong.
Converter:
Rest of code that I used for tests:
EDIT:
I firstly solved using Newtonsoft because I more familiar with and then converted to System.Text.Json. But I see that Serge added answer in Newtonsoft. However I solved a little diffrent using CustomCreationConverter, so I think it is worth sharing.
you can try this converter
classes