Невозможно обработать ошибку десериализации коллекции - PullRequest
1 голос
/ 24 апреля 2019

Я пытаюсь справиться с десерализацией объекта, который не соответствует некоторым моим классам.Я хотел бы, чтобы код выполнялся и не выполнялся только для недопустимых атрибутов, но метод десереализации возвращает нулевой объект.

Я использую этот метод в универсальном служебном классе, который десериализует некоторую строку для любого заданного типа.

Из тестового кода обработчик ошибок корректно работает с недопустимыми датами и другими недопустимыми типами и возвращает объект со значениями инициализации .NET по умолчанию.

Если я изменяю (или комментирую) коллекцию Itemsв подобъекте код работает.

string json = "{\"Id\":8,\"CreatedByUserId\":0,\"CreatedOnDate\":\"2019X-Y02Z-W06T18:A51:05.783\",\"LastModifiedByUserId\":1,\"LastModifiedOnDate\":\"2019-03-12T17:00:34.82\",\"OperationData\":{\"IsActive\":true,\"Items\":[{\"_Id\":1,\"Id_Value\":0,\"Id\":1},{\"_Id\":2,\"Id\":2},{\"Id\":1,\"IsDeleted\":false,\"Content\":{}}]}}";

TestType test = DeserealizeContent(json);

/*The convertion utility*/ 
 private static TestType DeserealizeContent(string data)
        {
            var settings = new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore,
                MissingMemberHandling = MissingMemberHandling.Ignore,
                Error = HandleDeserializationError
            };
            var r = JsonConvert.DeserializeObject<TestType>(data, settings);
            return r;
        }
        public static void HandleDeserializationError(object sender, ErrorEventArgs errorArgs)
        {
            errorArgs.ErrorContext.Handled = true;
        }

/*Supporting types*/
public class TestType {
        public int Id { get; set; }
        public DateTime CreatedOnDate { get; set; }
        public int CreatedByUserId { get; set; }
        public string Instructions { get; set; }
        public OperationDataType OperationData {get;set;}
    }

    public class OperationDataType {
        public bool IsActive { get; set; }
        public List<int> Items { get; set; }
    }

Я ожидал, что обработчик ошибок перехватит обработку исключительной ситуации и продолжит процесс, но вместо этого десериализация просто возвращает ноль в конце.

Если я изменю элементы списка на элементы списка, результат будет правильно проанализирован.

Мой ожидаемый результат будет: {"Id": 8, "CreatedByUserId": 0, "CreatedOnDate": null, "LastModifiedByUserId":1, «LastModifiedOnDate»: «2019-03-12T17: 00: 34.82», «OperationData»: {«IsActive»: true, «Items»: null}}

РЕДАКТИРОВАТЬ - обходной путь

Предложение от Яир (ниже) работает.Переключение из списка в список работает, как ожидалось, и исключение правильно обрабатывается.

1 Ответ

0 голосов
/ 24 апреля 2019

Элементы в вашем json не являются массивом int, так как вы хотите, чтобы он был List? Items - это массив объектов, которые можно посмотреть в формате json:

{
    "Id": 8,
    "CreatedByUserId": 0,
    "CreatedOnDate": "2019X-Y02Z-W06T18:A51:05.783",
    "LastModifiedByUserId": 1,
    "LastModifiedOnDate": "2019-03-12T17:00:34.82",
    "OperationData": {
        "IsActive": true,
        "Items": [{
                "_Id": 1,
                "Id_Value": 0,
                "Id": 1
            }, {
                "_Id": 2,
                "Id": 2
            }, {
                "Id": 1,
                "IsDeleted": false,
                "Content": {}
            }
        ]
    }
}

Вы можете сделать одну из трех вещей:

  1. обрабатывать содержимое json как строку или отображать его так, чтобы элементы были массивом [1,2,3].
  2. создайте класс элементов для элементов, включающих все необходимые поля, затем извлеките желаемое int.
  3. получите его как объект, как вы делаете сейчас, и используйте mirror () для получения нужного вам int.

Вы можете использовать эту функцию для отражения:

public static object GetPropValue(object src, string propName)
{
    return src.GetType().GetProperty(propName).GetValue(src, null);
}

, а затем используйте его так:

GetPropValue(test.OperationData.items[0], "Id")

EDIT Вы можете использовать это для десериализации json в общем виде:

Newtonsoft.Json.Linq.JObject jsonDeserialized  = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject<object>(json);

, а затем

вы можете сопоставить его вручную или с помощью автоматического инструмента с новым тестом TestType, который вам нужен, без элементов в нем.

вы можете получить такие значения:

test.Id = jsonDeserialized["Id"];
test.CreatedByUserId = jsonDeserialized["CreatedByUserId"];

и т. Д.

в соответствии с вашим последним комментарием я обнаружил, что если я изменил List<int> Items на List<long> Items, он работает так, как вы хотели. это что-то с примитивными типами и десериализацией, которые делают.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...