Reputation: 1066
I have a json file that looks like this:
{
"tags": {
"t1": {
"description": "bar"
},
"t2": {
"description": {
"$ref": "./t2.md"
}
}
}
}
and I would like to deserialize it with Json.NET like this:
var baz = JsonConvert.DeserializeObject<Baz>(File.ReadAllText(@"baz.json"));
//...
internal class Baz
{
[JsonProperty("tags")]
internal Tags Tags;
}
internal class Tags: Dictionary<string, Tag>
{
}
internal class Tag
{
[JsonProperty("description")]
internal Description Description;
}
internal class Description // FIXME: can be string, Dictionary or List
{
}
How can I define the Description
class, that can be either a string
or a Dictionary<string, string>
? I have tried inheriting an abstract method, but the deserializer always returned null
.
Upvotes: 1
Views: 252
Reputation: 7590
You can create a custom deserializer : https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm
public class DescriptionConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return false;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.String)
{
//If is string, return the string
return serializer.Deserialize(reader, objectType);
}
else
{
//If not string, try get the field '$ref'
var obj = JObject.Load(reader);
if (obj["$ref"] != null)
return obj["$ref"].ToString();
else
throw new InvalidOperationException("Invalid Json");
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Then you can specify this converter in your model :
internal class Baz
{
[JsonProperty("tags")]
internal Tags Tags;
}
internal class Tags : Dictionary<string, Tag>
{
}
internal class Tag
{
[JsonProperty("description")]
[JsonConverter(typeof(DescriptionConverter))]
internal string Description;
}
Finally, you can deserialize the json :
static void Main(string[] args)
{
string json = @"{
'tags': {
't1': {
'description': 'bar'
},
't2': {
'description': {
'$ref': './t2.md'
}
}
}
}";
var baz = JsonConvert.DeserializeObject<Baz>(json);
Console.WriteLine("t1 : " + baz.Tags["t1"].Description);
Console.WriteLine("t2 : " + baz.Tags["t2"].Description);
}
Output :
t1 : bar
t2 : ./t2.md
Upvotes: 2