2016-05-21 3 views
0

Я пытаюсь создать инструмент, который будет сравнивать объекты JSON с некоторыми объектами C# POCO, которые у меня есть. Этот инструмент поможет мне обнаружить, когда новые поля добавлены или старые удалены по сравнению с моими объектами.Обнаруживать свойства не в JSON при десериализации с помощью Json.Net

Корпус «нового поля» прост. В SerializerSettings я установил свойство MissingMemberHandling на Error и добавил слушателя к событию Error. Когда поле C# отсутствует, событие вызывается с подробной информацией.

Корпус «старого поля» (где поле/свойство C# не задано) представляется сложнее решить. См. Примерный код ниже. Этот код будет работать без проблем и обнаруживать случаи, когда появляется новое поле JSON, но не обнаружит, когда Field2 не находится в JSON.

class TestObject 
{ 
    public int Field1 { get; set; } 

    public int Field2 { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     string exampleJson = @"{ ""Field1"": 1 }"; 

     JsonSerializerSettings settings = new JsonSerializerSettings(); 
     settings.MissingMemberHandling = MissingMemberHandling.Error; 
     settings.Error = Error; 

     try 
     { 
      TestObject obj = JsonConvert.DeserializeObject<TestObject>(exampleJson, settings); 

      Console.WriteLine("Object had no errors"); 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("Object had errors"); 
     } 
    } 

    private static void Error(object sender, ErrorEventArgs errorEventArgs) 
    { 
     Console.WriteLine(errorEventArgs.ErrorContext.Path + " had " + errorEventArgs.ErrorContext.Error.Message); 
    } 
} 

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

Наконец. Я не могу добавить атрибуты [DataMember(IsRequired = true)] или [JsonProperty(Required = Required.Always)].

ответ

0

У меня может быть работоспособное решение.

Создав ContractResolver, я могу установить все свойства Required во время выполнения. Это даст ошибку, не меняя свою модель, но это дает лишь первую ошибку ... если вы установите Handled в true в Error обратного вызова:

class TestObject 
{ 

    public int Field1 { get; set; } 

    public int Field2 { get; set; } 

    public int Field3 { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     string exampleJson = @"{ ""Field1"": 1, ""Field4"": 1 }"; 

     JsonSerializerSettings settings = new JsonSerializerSettings(); 
     settings.MissingMemberHandling = MissingMemberHandling.Error; 
     settings.ContractResolver = new ContractResolver(); 
     settings.Error = Error; 

     try 
     { 
      TestObject obj = JsonConvert.DeserializeObject<TestObject>(exampleJson, settings); 

      Console.WriteLine("Object had no errors"); 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("Object had errors"); 
     } 
    } 

    private static void Error(object sender, ErrorEventArgs errorEventArgs) 
    { 
     errorEventArgs.ErrorContext.Handled = true; 
     Console.WriteLine(errorEventArgs.ErrorContext.Path + " had " + errorEventArgs.ErrorContext.Error.Message); 
    } 
} 

internal class ContractResolver : DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     JsonProperty res = base.CreateProperty(member, memberSerialization); 

     res.Required = Required.AllowNull; 

     return res; 
    } 
} 
Смежные вопросы