我有一个类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。但是我不明白为什么必须使用
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()
:
从源读取下一个JSON令牌作为String。
但是,在调用JsonConverter.ReadJson()
时,读取器已经位于与要反序列化的对象相对应的第一个JSON令牌上。因此,通过调用ReadAsString()
可以放弃该值,并尝试读取流中的下一个标记-但是没有,因此抛出异常。
此外,在ReadJson()
的末尾,您的代码必须已将读取器定位在与要转换的对象相对应的最后一个JSON令牌上。因此,在JSON只是简单的原语的情况下,阅读器根本不应该变得高级。
确保阅读器始终由ReadJson()
正确定位的一种简单方法是调用JToken.Load()
。这总是使读取器位于已加载令牌的末尾。之后,您可以检查以确保加载了预期的内容。例如,如果JSON的对象应该是字符串,而不是使阅读器的位置不正确,则转换器应抛出异常,而不是使阅读器的位置不正确。
Json.Net: Serialize/Deserialize property as a value, not as an object中的StringIdConverter
给出了一个示例。您可以如下修改它:
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/