There is a server which, in the case of an invalid request, returns a deserialized JSON string representing an object of type EXCEPTION . Depending on the type of error, an object can have a completely different structure from a simple one:

 public class simpleException { public string Reason {get;set;} public string Controller {get;set;} } 

To process the received response and understand what exactly the exception is, there is a method:

 try { var Err = JsonConvert.DeserializeObject<simpleException>(responsedBodyStr); } catch (JsonSerializationException) { try { var Err = JsonConvert.DeserializeObject<TrsException>(responsedBodyStr); } catch(JsonSerializationException) { try {.... } } 

Try try-catch attachment try-catch much more and they turn into awful spaghetti code. Actually the question is - if you are faced with similar situations, then share your advice on how to improve the code?

upd I get the exception string like this:

 catch (WebException ex) { ExcStr= new StreamReader(ex.Response.GetResponseStream()).ReadToEnd(), 
  • Depending on the type of error, the object may have a completely different structure - is the type of error indicated somewhere? - Grundy
  • @Grundy in json is not, only in WebException you can see the status code and Status Description - Sergey
  • There is a server which, in the case of an invalid request, returns a deserialized JSON string representing an object of type EXCEPTION - it is not entirely clear. An object of type Exception comes to you? - Andrei NOP
  • @AndreyNOP server on the asp fields of the object are serialized into the json string and returned with the server response. - Sergey
  • Well, what does the JSON string, representing an EXCEPTION object, mean? Is this some kind of base class? Can we deserialize into it? - Andrei NOP

2 answers 2

As a first approximation, expand nesting into a loop. Naive example:

The processor-composite collects handlers for an exception and banishes them

 public class ExceptionProc { private List<Func<string, bool>> _processors = new List<System.Func<string, bool>>(); public void AddProc(Func<string, bool> proc) { _processors.Add(proc); } public bool ProcessException(string input) { foreach(var proc in _processors) { try { if (proc(input)) return true; } catch(Exception) { /// logging } } return false; } } 

How to use

 var processor = new ExceptionProc(); processor.AddProc((responsedBodyStr) => { var Err = JsonConvert.DeserializeObject<simpleException>(responsedBodyStr); // .. do stuff return true; }); processor.AddProc((responsedBodyStr) => { var Err = JsonConvert.DeserializeObject<TrsException>(responsedBodyStr); // .. do stuff return true; }); if (!processor.ProcessException(someString)) ; { // logging fail } 

As a result, the addition of the handler has become an elementary matter. Try-catch can be pushed into a handler, a handler can be made a class with the CanProcess method, well, a lot more can be done, depending on the task

  • Is there a way to transfer to < > type dynamically? in fact, in JsonConvert.DeserializeObject<TrsException> only the type of the exception always changes. - Sergey
  • @ Sergey of course exists. Write a generic function, for example bool MyFunction<T>(string response) { JsonConvert.DeserializeObject<T>(response); ..... } bool MyFunction<T>(string response) { JsonConvert.DeserializeObject<T>(response); ..... } MyFunction<MyException>(response); as MyFunction<MyException>(response); - tym32167

A JSON object must have some kind of error code, either by HTTP code there must be differentiation or inheritance. It’s too stupid to try to guess so much, especially through full parsing and exceptions.

The solution might be LINQ to JSON :

 JObject o = JObject.Parse(@"{ 'CPU': 'Intel', 'Drives': [ 'DVD read/writer', '500 gigabyte hard drive' ] }"); string cpu = (string)o["CPU"]; // Intel string firstDrive = (string)o["Drives"][0]; // DVD read/writer IList<string> allDrives = o["Drives"].Select(t => (string)t).ToList(); // DVD read/writer // 500 gigabyte hard drive