【发布时间】:2021-04-06 16:23:23
【问题描述】:
我有以下自定义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());
}
}
}
它应该有助于(反)序列化以下类:
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;
}
}
}
反序列化代码为:
cached = JsonConvert.DeserializeObject<Dictionary<uint, List<RefLocCacheItem>>>(File.ReadAllText(cacheFile));
各自的序列化代码为:
File.WriteAllText(cacheFile, JsonConvert.SerializeObject(cached, Newtonsoft.Json.Formatting.Indented));
这是一个示例 json 文件:
{
"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": []
}
因此,如您所见,序列化工作正常。但是,反序列化代码从不调用转换器的ReadJson 函数。事实上,它根本不起作用!没有失败,但返回的字典包含 RefLocCacheItems 和 null 文件路径和空文本跨度:
过去我多次使用 Json.Net,但我不明白我现在做错了什么。
我使用的是最新版本 - 13.0.1,但我检查了一些旧版本 - 同样的事情。所以,这是我的错,但在哪里?
澄清编辑
FilePath 属性未反序列化。而且它与转换器无关。而转换器 - ReadJson 方法甚至没有被调用!
【问题讨论】:
-
我还没有调试你的代码,但你可能想要
reader.Value而不是reader.ReadAsString()。为什么请参阅this answer 至Custom JsonConverter not working when using JsonReader instead of JsonSerializer。事实上,这可能是重复的,同意吗? -
@dbc - 感谢您的回复。问题是 FilePath 也没有反序列化!
ReadJson甚至没有被调用! -
您的所有属性都有私有设置器。尝试将
[JsonProperty]添加到属性中,或者将它们公开。 -
好吧,一旦
JsonReader定位错误,所有类型的值都会被丢弃。 -
@dbc - 从不调用它。