Newtonsoft.Json v11 - DeserializeObject throws JsonReaderExc



我们已经将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.JsonReaderException"在 牛顿软件.Json.dll

其他信息:未定义的令牌不是有效的 System.Nullable'1[System.Int64].路径"[0].发票 ID",第 1 行。

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

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

但仍然是同样的错误。必须进行哪些更改才能使其在 11.0.1 上运行。恐怕我们无法容纳 JSON 输出,因为这来自第三方 API。

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 发行说明:

修复 - 修复了读取可为空的长文章未定义时不出错的问题

因此,如果我们假设您的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
}

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

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?的属性调用):

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

相关内容

  • 没有找到相关文章

最新更新