Deserializing MandrillApp Webhook response

2019-02-25 13:34发布

MandrillApp API supposedly sends a JSON-encoded array of the messages with the mime type application/x-www-form-urlencoded.

The problem I have encountered is that the data received looks like:

mandrill_events=%5B%7B%22event%22%3A%22send%22
%2C%22msg%22%3A%7B%22ts%22%3A136510999...etc

Url decoded it is:

mandrill_events=[{"event":"send","msg":{
"ts":1365109999,"subject"...etc

I try to deserialize this string into a class that represents the JSON data but the JSON.NET deserializer spits out an error.

Code

m = JsonConvert.DeserializeObject<MandrillEvents>(s);

Exception

Unexpected character encountered while parsing value: m. Path '', line 0, position 0.

From what I have I think that the mandrill_events= portion of the string is invalid.

  • Should this string be able to be deserialized?
  • Is there an option that I am missing when deserializing?
  • How should I approach this?

1条回答
【Aperson】
2楼-- · 2019-02-25 14:12

mandrill_events= is not valid JSON. If you take that out you should be able to parse it.

string validJson = originalText.Replace("mandrill_events=", ""); 
var m = JsonConvert.DeserializeObject<MandrillEvents[]>(validJson);

If that doesn't work, we would need to see more of the text to determine what else isn't valid JSON. JSON is great because it only has a few simple datatypes. Object, Array, Boolean, String, Integer, etc. See this for all valid types, http://json.org/.

As Brian Rogers mentioned you are also deserializing into the wrong type (you have an array of objects, not a single object).

If you want to check if the entire json string is valid you can use

JArray array = JArray.Parse(validJson);

If you are ever unsure you can use

JToken token = JToken.Parse(validJson);

Which works on both objects, arrays and values. I would still say deserializing into a model is better because you get strong typing, but this can at least assure you that you have valid JSON before you attempt to build the model.


Visual Studio 2012 has a VERY cool feature where if you copy the valid JSON text, click edit > paste as JSON class and it will actually paste the JSON as a valid C# class which you then know you can deserialize into. This makes building a POCO model from complex JSON much easier and less error prone than doing it manually.


In response to your question

Are you able to comment on why they would send the response like they have?

I think that is strange and puts more work on the client to be able to parse / read their response. You can represent almost any data with JSON which is why it's such a popular choice as a data-exchange format for web API's. All modern languages have good JSON parers as well. It's universal and well understood. When you come up with any custom format to send data that requires a client to write their own parser or even use regex then you are re-inventing the wheel IMO. In this case they are embedding one format into another which is still pretty ugly and stops you from using a single parser.

As far as the WHY, it could be for backward compatibility. They exposed their API as application/x-www-form-urlencoded originally and didn't want to break existing clients so they continue using it but embed JSON objects. From their docs (mandrillapp.com/api/docs/webhooks.JSON.html), looks like all responses are JSON, you could double check that you are using the proper url and also that you send accept: application/json in the request header. This is the common HTTP way of telling the server you want back a JSON response.

查看更多
登录 后发表回答