首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用JsonReader而不是JsonSerializer时,自定义JsonSerializer无法工作

使用JsonReader而不是JsonSerializer时,自定义JsonSerializer无法工作
EN

Stack Overflow用户
提问于 2017-09-03 15:18:02
回答 2查看 2.9K关注 0票数 2

我有一个类Foo及其FooConverter,定义如下:

代码语言:javascript
复制
[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);
    }
}

串行化很好。但在反序列化时:

代码语言:javascript
复制
var foo = JsonConvert.DeserializeObject<Foo>("\"something\"");

它抛出JsonSerializationException,因为reader.ReadAsString是空的。

但是我不明白为什么它必须是null. reader.ReadAsString工作得很好,如果我像这样手动地做的话:

代码语言:javascript
复制
var reader = new JsonTextReader(new StringReader("\"something\""));
var str = reader.ReadAsString(); // str is now `something` NOT null

虽然我可以在FooConverter中使用serializer.Deserialize<string>(reader)来修复ReadJson,但我仍然想了解为什么reader.ReadAsStringFooConverter.ReadJson中失败。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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/3744182https://stackoverflow.com/a/40480742/3744182给出了一个例子。您可以按以下方式修改它:

代码语言:javascript
复制
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 };
    }
票数 9
EN

Stack Overflow用户

发布于 2017-09-03 15:58:27

您的"\"something\""不是有效的JSON,它只是一个转义字符串。JSON = JavaScript对象表示法,其中空对象被定义为{}

带有状态的对象只是一个字典结构,其中键有值。您的Foo类型有一个属性Something,它是键,需要为它分配一个值。因此,尝试像这样的JSON对象:

代码语言:javascript
复制
{ Something: "a value" }

在C#中,它将被转换成这样:

代码语言:javascript
复制
var foo = JsonConvert.DeserializeObject<Foo>("{\"Something\":\"a value\"}");
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46024882

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档