繁体   English   中英

Newtonsoft.Json v11-DeserializeObject引发JsonReaderException

[英]Newtonsoft.Json v11 - DeserializeObject throws JsonReaderException

我们已经将Newtonsoft.Json从10.0.3升级到11.0.1,并且以前一直有效的代码不再起作用。

我们有以下JSON:

[{"mail-type":"registration","response":"250 OK id=1UjnNr-gdf-C0 ","invoice-id":,"email":"testuser08@test.com"}]

我们调用以下方法:

var events = JsonConvert.DeserializeObject<Event[]>(jsonEvents);

在10.0.3上可以正常工作,但在11.0.1上则不能。 在此版本上,引发以下异常:

引发异常:Newtonsoft.Json.dll中的'Newtonsoft.Json.JsonReaderException'

附加信息:未定义的令牌不是有效的System.Nullable`1 [System.Int64]。 路径'[0] .invoice-id',第1行。

我试图将以下选项传递给DeserializeObject

var settings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore,
    MissingMemberHandling = MissingMemberHandling.Ignore
};

但是还是一样的错误。 必须进行哪些更改才能使其在11.0.1上运行。 我很抱歉,我们无法容纳JSON输出,因为它来自第三方API。

您可以使用自定义转换器实现解决方法:

internal class NullableLongFixupConverter : JsonConverter {
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
        writer.WriteValue(value);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
        // if token undefined - return null
        if (reader.TokenType == JsonToken.Undefined)
            return null;
        // otherwise - value
        return (long?) reader.Value;
    }

    public override bool CanConvert(Type objectType) {
        return objectType == typeof(long?);
    }
}

然后,您可以使用它来装饰属性:

class Event {
    [JsonProperty("invoice-id")]        
    [JsonConverter(typeof(NullableLongFixupConverter))]
    public long? InvoiceId { get; set; }
}

或全局注册(将仅对long?类型的属性调用long? ):

JsonConvert.DefaultSettings = () =>
{
    var s = new JsonSerializerSettings();                    
    s.Converters.Add(new NullableLongFixupConverter());
    return s;
};

您的JSON示例格式不正确。 如果我将您的JSON上传到https://jsonlint.com/,则会生成以下错误:

 Error: Parse error on line 4: ...0 ", "invoice-id": , "email": "testuse ----------------------^ Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '[', got ',' 

有问题的行如下:

"invoice-id": ,

按照JSON标准 ,需要有对之间的值:, 但是,为什么这在Json.NET 10.0中起作用? 显然,这是一个错误,已修复。 根据11.0.1发行说明

修复-修复了读取可为空的long时未出错的错误

因此,如果我们假设您的Event类型如下所示:

public partial class Event
{
    [JsonProperty("invoice-id")]
    public long? InvoiceId { get; set; }

    // Other properties as required
}

然后在10.0中,可以使用此类型成功反序列化JSON,但在11.0中则不能。 但是,如果我们将InvoiceId更改为int?

public partial class Event
{
    [JsonProperty("invoice-id")]
    public int? InvoiceId { get; set; }

    // Other properties as required
}

在两个版本中均失败。 因此,解决方法似乎是处理int? long? 始终如一。

理想情况下,您应该询问谁向您发送了此类JSON进行修复,以使其符合http://www.json.org/RFC 8259的定义。 但是,如果仍然需要以与Json.NET 10.0相同的方式解析此类JSON,则可以按以下方式引入TolerantNullableLongConverter

public class TolerantNullableLongConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(long?);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        if (reader.TokenType == JsonToken.Undefined)
            return null;
        if (reader.Value is long)
            return reader.Value;
        // string or int or decimal or ...
        return serializer.Deserialize<long>(reader);
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

并将其应用于您的类型,如下所示:

public partial class Event
{
    [JsonProperty("invoice-id")]
    [JsonConverter(typeof(TolerantNullableLongConverter))]
    public long? InvoiceId { get; set; }

    // Other properties as required
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM