我有一个课程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
失败的原因。
答案 0 :(得分:2)
根据documentation,JsonReader.ReadAsString()
:
从源中读取下一个 JSON令牌作为字符串。
但是,当调用JsonConverter.ReadJson()
时,阅读器已经定位在与要反序列化的对象相对应的第一个JSON令牌上。因此,通过调用ReadAsString()
,您放弃该值并尝试读取流中的下一个标记 - 但没有,所以您抛出异常。
此外,在ReadJson()
结束时,您的代码必须将阅读器定位在与要转换的对象相对应的最后一个JSON令牌上。因此,在JSON只是原始的情况下,读者根本不应该先进。
保证ReadJson()
始终正确定位读者的一种简单方法是致电JToken.Load()
。这总是使读取器位于加载的令牌的末尾。之后,您可以检查加载的内容是否符合预期。例如,如果JSON有一个预期字符串的对象,而不是让读者错误定位,转换器应该抛出异常,而不是让读者错误定位。
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 };
}
答案 1 :(得分:0)
您的"\"something\""
无效JSON,它只是一个转义字符串。 JSON = JavaScript Object Notation,其中空对象定义为{}
。
具有state的对象只是一个字典结构,其中键具有值。您的Foo
类型具有属性Something
,这是关键,需要为其分配值。所以尝试这样的JSON对象:
{ Something: "a value" }
在C#中会像这样转换:
var foo = JsonConvert.DeserializeObject<Foo>("{\"Something\":\"a value\"}");