我有一个类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中失败。
发布于 2017-09-03 17:04:46
你的问题是,根据文档,JsonReader.ReadAsString()
将next JSON令牌从源读取为字符串。
但是,当调用JsonConverter.ReadJson()时,读取器已经定位在对应于正在反序列化的对象的第一个JSON令牌上。因此,通过调用ReadAsString(),您放弃了该值,并尝试读取流中的下一个令牌--但是没有,所以抛出了一个异常。
此外,在ReadJson()的末尾,您的代码必须将读取器定位在与正在转换的对象对应的最后一个JSON令牌上。因此,在JSON只是一个原语的情况下,读取器根本不应该被高级化。
确保ReadJson()始终正确定位阅读器的一种简单方法是调用JToken.Load()。这总是使读取器位于加载的令牌的末尾。之后,您可以检查加载的内容是否与预期的一样。例如,如果JSON有一个需要字符串的对象,而不是让读取器处于错误的位置,转换器应该抛出一个异常,而不是让读取器处于错误的位置。
来自https://stackoverflow.com/a/40480742/3744182的https://stackoverflow.com/a/40480742/3744182给出了一个例子。您可以按以下方式修改它:
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 };
}发布于 2017-09-03 15:58:27
您的"\"something\""不是有效的JSON,它只是一个转义字符串。JSON = JavaScript对象表示法,其中空对象被定义为{}。
带有状态的对象只是一个字典结构,其中键有值。您的Foo类型有一个属性Something,它是键,需要为它分配一个值。因此,尝试像这样的JSON对象:
{ Something: "a value" }在C#中,它将被转换成这样:
var foo = JsonConvert.DeserializeObject<Foo>("{\"Something\":\"a value\"}");https://stackoverflow.com/questions/46024882
复制相似问题