我有一个类Foo
及其 FooConverter
定义如下:
[JsonConverter(typeof(FooConverter))]
public class Foo
{
public string Something { get; set; }
}
public class FooConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(((Foo)value).Something);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var str = reader.ReadAsString();
if (str == null)
{
throw new JsonSerializationException();
}
// return new Foo {Something = serializer.Deserialize<string>(reader)};
return new Foo {Something = str};
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Foo);
}
}
序列化工作正常。但是在反序列化时:
var foo = JsonConvert.DeserializeObject<Foo>("\"something\"");
它抛出 JsonSerializationException
因为reader.ReadAsString
为空。
但我不明白为什么它必须是 null
... reader.ReadAsString
如果我像这样手动进行操作,可以完美地找到:
var reader = new JsonTextReader(new StringReader("\"something\""));
var str = reader.ReadAsString(); // str is now `something` NOT null
尽管我可以修复 FooConverter
通过使用 serializer.Deserialize<string>(reader)
在 ReadJson
,我还是想明白为什么reader.ReadAsString
在 FooConverter.ReadJson
中失败.
最佳答案
你的问题是,根据documentation , JsonReader.ReadAsString()
:
Reads the next JSON token from the source as a String.
然而,当JsonConverter.ReadJson()
被调用时,读者已经定位到与被反序列化的对象对应的第一个 JSON token 。因此,通过调用 ReadAsString()
,您丢弃了该值并尝试读取流中的下一个标记——但是没有标记,因此您抛出异常。
此外,在 ReadJson()
的末尾,您的代码必须将读取器定位到与要转换的对象对应的最后一个 JSON 标记处。因此,在 JSON 只是原始数据的情况下,读者根本不应该有任何进步。
保证读取器始终由 ReadJson()
正确定位的一种简单方法是调用 JToken.Load()
.这总是使读取器位于已加载 token 的末尾。之后,您可以检查加载的内容是否符合预期。例如,如果 JSON 有一个对象,其中需要一个字符串,而不是让读取器定位不正确,转换器应该抛出异常,而不是让读取器定位不正确。
StringIdConverter
来自 Json.Net: Serialize/Deserialize property as a value, not as an object 举了一个例子。您可以按如下方式修改它:
public class FooConverter : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var token = JToken.Load(reader);
if (!(token is JValue))
throw new JsonSerializationException("Token was not a primitive");
return new Foo { Something = (string)token };
}
关于c# - 使用 JsonReader 而不是 JsonSerializer 时自定义 JsonConverter 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46024882/