无法处理集合退化错误

时间:2019-04-24 08:57:53

标签: c# collections json.net

我试图处理反密封的对象,该对象不符合我的某些课程。我希望代码能够执行并仅在无效属性上失败,但是反实现方法返回的是空对象。

我在泛型实用程序类中使用此方法,该类将某些字符串反实现为任何给定类型。

根据测试代码,错误处理程序可以在无效日期和其他无效类型上正常工作,并返回具有默认.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; }
    }

我原本希望错误处理程序能够捕获异常并继续执行该过程,但是反现实化最终只会返回null。

如果我将“列表项”更改为“列表项”,则结果将被正确解析。

我的预期结果是: {     “ Id”:8     “ CreatedByUserId”:0,     “ CreatedOnDate”:null,     “ LastModifiedByUserId”:1     “ LastModifiedOnDate”:“ 2019-03-12T17:00:34.82”,     “ OperationData”:{         “ IsActive”:是,         “项目”:null     } }

编辑-解决方法

Yair(bellow)的建议起作用了。 从列表更改为列表可以按预期工作,并且可以正确处理异常。

1 个答案:

答案 0 :(得分:0)

您的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内容处理为字符串或将其映射为项目,使其成为int数组[1,2,3]。
  2. 为包含所有需要的字段的项目创建项目类,然后提取所需的int。
  3. 像现在一样将其作为对象获取,并使用反射()获取所需的int。

您可以使用此功能进行反射:

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

然后像这样使用它:

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

编辑 您可以使用此方法以通用方式反序列化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,它会按您的意愿工作。这是具有原始类型和反序列化功能的解析。