0

I have a callback web method that Facebook is calling. Unfortunately, the purpose of the call using this single url is determined solely by the structure of the object (json) that is passed in the Post body. Right now, I am thinking of:

try { Class1 obj1 = JsonConvert.DeserializeObject<Class1>(rawData); 
      //code to run if data is of Class1 ...
    }
catch
{ try { Class2 obj2 = JsonConvert.DeserializeObject<Class2>(rawData);
        //code to run if data is of Class2 ... 
      }
  catch
      { Class3 obj3 = JsonConvert.DeserializeObject<Class3>(rawData); 
        //code to run if data is of Class3...
      }
}

Is there a cleaner better way than the above?

4
  • If possible, it might make sense to configure different endpoints for each status update type. Alternatively, the class would store all the possible information, and then decide how to process it once it's been deserialized Commented Jun 4, 2016 at 15:05
  • 6
    Do you have any way to understand from the raw data what kind of class should be deserialized? Using exceptions to drive your code should be avoided as much as possible Commented Jun 4, 2016 at 15:05
  • Do you have examples of the json? maybe you can find out which type to use before calling DeserializeObject<T> Commented Jun 4, 2016 at 15:11
  • This is truly a bad practice. You should deserialize to (or better, make your model a) JObject and then determine from its properties to which class convert it (using jObject.ToObject<T>). Commented Jun 4, 2016 at 15:22

1 Answer 1

3

Ideally, you shouldn't use exceptions to drive decisions on code paths that do not deal with exceptional situations. If this is something that you cannot avoid, you could set up a loop that tries different classes, like this:

var deserializers = new Func<string,object>[] {
    (rawData) => JsonConvert.DeserializeObject<Class1>(rawData)
,   (rawData) => JsonConvert.DeserializeObject<Class2>(rawData)
,   (rawData) => JsonConvert.DeserializeObject<Class3>(rawData)
};
object result = null;
foreach (var d in deserializers) {
    try {
        result = d(rawData);
        break;
    } catch {
        // Conversion was unsuccessful
    }
}

If deserializing went OK, break statement is reached, and your loop exits. Otherwise, the loop continues to the next iteration, until the loop succeeds, or we run out of deserializers.

Note: An explicit cast may be required in order to put functors into an array:

(rawData) => (object)JsonConvert.DeserializeObject<Class1>(rawData)
Sign up to request clarification or add additional context in comments.

2 Comments

I wonder if one can just do new Func<string, object>[] { JsonConvert.DeserializeObject<Class1>, JsonConvert.DeserializeObject<Class2>, JsonConvert.DeserializeObject<Class3>, }.
@JeppeStigNielsen I am not sure about that, because JsonConvert.DeserializeObject<ClassXYZ> have different return types. I am not even sure if the syntax I used would work without an explicit cast.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.