I have the following custom JsonConverter
:
using Microsoft.CodeAnalysis.Text;
using Newtonsoft.Json;
using System;
namespace CSTool.Json
{
public class TextSpanJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType == typeof(TextSpan);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var str = reader.ReadAsString();
var delim = str.IndexOf('.');
var start = int.Parse(str.AsSpan(1, delim - 1));
var end = int.Parse(str.AsSpan(delim + 2, str.Length - delim - 3));
return TextSpan.FromBounds(start, end);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
}
}
It is supposed to help (de)serialize the following class:
using CSTool.Json;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Newtonsoft.Json;
namespace CSTool.ObjectModel
{
public class RefLocCacheItem
{
public string FilePath { get; private set; }
[JsonConverter(typeof(TextSpanJsonConverter))]
public TextSpan TextSpan { get; private set; }
[JsonConverter(typeof(LinePositionSpanJsonConverter))]
public LinePositionSpan LinePositionSpan { get; private set; }
public RefLocCacheItem()
{
}
public RefLocCacheItem(Location o) : this(o.SourceTree.FilePath, o.SourceSpan, o.GetLineSpan().Span)
{
}
public RefLocCacheItem(string filePath, TextSpan textSpan, LinePositionSpan linePositionSpan)
{
FilePath = filePath;
TextSpan = textSpan;
LinePositionSpan = linePositionSpan;
}
}
}
The deserialization code is:
cached = JsonConvert.DeserializeObject<Dictionary<uint, List<RefLocCacheItem>>>(File.ReadAllText(cacheFile));
The respective serialization code is:
File.WriteAllText(cacheFile, JsonConvert.SerializeObject(cached, Newtonsoft.Json.Formatting.Indented));
And here is a sample json file:
{
"100666494": [],
"100666517": [],
"67111627": [
{
"FilePath": "c:\xyz\\tip\\MySourceFile.cs",
"TextSpan": "[105331..105379)",
"LinePositionSpan": "(2379,51)-(2379,99)"
}
],
"67111628": [
{
"FilePath": "c:\xyz\\tip\\MySourceFile.cs",
"TextSpan": "[136762..136795)",
"LinePositionSpan": "(2953,30)-(2953,63)"
}
],
"100666534": []
}
So, as you can see, serialization works fine. However, the deserialization code never invokes the converter's ReadJson
function. In fact, it does not work at all! There is no failure, but the returned dictionary contains RefLocCacheItem
s with null
file paths and empty text spans:
I used Json.Net many times in the past and I don't understand what am I doing wrong now.
I use the latest version - 13.0.1, but I checked a few older versions - same thing. So, it is my fault, but where?
Clarification edit
The FilePath
property is not deserialized. And it has nothing to do with the converter. And the converter - the ReadJson
method is not even called!