Ошибка Json.Net DeserializeObject с OData.Delta - только целые числа
Эта проблема затрагивает мой метод ASP.Net WebApi Patch, который выглядит примерно так:
public MyModel Patch(int id, [FromBody]Delta<MyModel> newRecord){/*stuff here*/}
Но проблема не в WebApi, а в сбое между Json.Net и OData.Delta.
Проблема вJsonConvert.DeserializeObject не видит целые числа объектов OData.Delta и мне интересно, если есть обходной путь или исправить, я могу применить.
ОБНОВЛЕНИЕ: написал код (см. Ниже) в библиотеке Json.Net, который исправит это. Просто нужно включить его в следующее обновление (если Джеймс Ньютон-Кинг это позволяет)
ОБНОВЛЕНИЕ 2: После дальнейшего тестирования я решил, что лучше всего прекратить использовать OData.Delta и написать свой собственный (см. Ответ)
Модульные тесты, чтобы доказать, что проблема существует (используя утверждения, перемещенные ниже для ясности)
Тест 1: Сбой с int (Int32):
class TestObjWithInt
{
public int Int { get; set; }
}
[TestMethod]
public void IsApplied_When_IntIsDeserializedToDelta()
{
string testData = "{\"Int\":1}";
var deserializedDelta = JsonConvert.DeserializeObject<Delta<TestObjWithInt>>(testData);
var result = deserializedDelta.GetChangedPropertyNames().Contains("Int");
Assert.IsTrue(result);
}
Тест 2: Успех с длинной (Int64)
class TestObjWithLong
{
public long Long { get; set; }
}
[TestMethod]
public void IsApplied_When_LongIsDeserializedToDelta()
{
string testData = "{\"Long\":1}";
var deserializedDelta = JsonConvert.DeserializeObject<Delta<TestObjWithLong>>(testData);
var result = deserializedDelta.GetChangedPropertyNames().Contains("Long");
Assert.IsTrue(result);
}
И просто чтобы быть уверенным, что десериализация работает с самого начала, оба эти теста проходят.
[TestMethod]
public void IsApplied_When_LongIsDeserializedToTestObject()
{
string testData = "{\"Long\":1}";
var deserializedObject = JsonConvert.DeserializeObject<TestObjWithLong>(testData);
var result = deserializedObject.Long == 1;
Assert.IsTrue(result);
}
[TestMethod]
public void IsApplied_When_IntIsDeserializedToTestObject()
{
string testData = "{\"Int\":1}";
var deserializedObject = JsonConvert.DeserializeObject<TestObjWithInt>(testData);
var result = deserializedObject.Int == 1;
Assert.IsTrue(result);
}
я нашелэтот Отчет об ошибке OData, который звучит как похожая проблема, но он старый и закрытый, поэтому, вероятно, нет.
Любая помощь будет отличной.
Используя операторы (из верхней части тестового файла):
using System;
using System.Linq;
using System.Web.Http.OData;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
Решение, если оно принято Джеймсом Ньютоном-Кингом, - перейти на выпуск 6.0.6. Замените строку JsonSerializerInternalReader.cs 1581:
contract.TrySetMember(newObject, memberName, value);
с:
bool done = false;
while (!(done = done || contract.TrySetMember(newObject, memberName, value)))
{
switch (reader.TokenType)
{
case JsonToken.Integer:
if (value is long && ((long)value) <= Int32.MaxValue && ((long)value) >= Int32.MinValue)
value = Convert.ToInt32(value);
//Add else if (...) to cast to other data types here (none additional required to date).
else
done = true;
break;
default:
done = true;
break;
}
}