This is the absolute simplest version of this question (a subset of it).
using System;
using System.Collections.Generic;
using System.Text.Json;
public class Program
{
public class Subscription
{
public bool HasRead { get; set; } = true;
public string TimeStamp { get; set; } = "";
}
public static void Main()
{
// this input format is a requirement. It cannot be changed.
string json = @"
{
""305FDF11-25E7-43DE-B09D-DFFC17C79599"": {
""hasRead"": true, // EDIT: Removed the double quotes around the boolean. That was not the core issue.
""Timestamp"": ""XXX""
}
}
";
// I'm trying to find the correct deserialization type in C#
var deser = JsonSerializer.Deserialize<KeyValuePair<string, Subscription>>(json,
new JsonSerializerOptions(JsonSerializerDefaults.Web));
// System.Text.Json.JsonException:
//'The JSON value could not be converted to
//System.Collections.Generic.KeyValuePair
}
}
I can’t understand why that can’t be deserialized.
Note: I’m obsessing over the KeyValuePair
type but maybe it has to do with the casing of the fields or something else obvious.
Other note : It still fails when I change KeyValuePair<string, Subscription>
to KeyValuePair<string, object>
to make it more permissive.
5
Answers
The default serialization of type KeyValuePair<string, Subscription> looks like this:
To change this behavior you need to write your own converter derrived from JsonConverter class.
Also note that true value should be without quotes.
First of all, your JSON does not conform to default serialization of
KeyValuePair<string, Subscription>
, I’d recommend switching the type toDictionary<string, Subscription>
. As well, default JSON deserializer is unable to deserialize your JSON. I’d recommend usingNewtonsoft.Json
Like this you’d get output of
Subscription timestamp is XXX
.You have two issues.
1)
true
is surrounded by quotes. By default that will not deserialise to a boolean but a string. You can change the type ofHasRead
in theSubscription
class to fix the issue. If you want a boolean property then you could add something like:You cannot deserialise directly to a
KeyValuePair
as that has namedKey
andValue
properties. Instead you can deserialise to aDictionary
:If you want to get a
KeyValuePair
you can do this:var kvp = deser.First()
We can use type Dictionary<String,Subscription> to achieve it.
I tried to print all values.
Output is :-
Note :- We should try to match case in json and class properties. Else, We will get null/default values. I have modified Timestamp to TimeStamp in JSON string.