Neil Dobson
Neil Dobson

Reputation: 1259

How to parse JSON array from message headers with a Mailgun webhook

A typical set of message headers from a mailgun callback looks like this:

[["Received", "by luna.mailgun.net with SMTP mgrt 8765806286401; Fri, 14 Jun 2013 02:25:33 +0000"],
["Content-Type", ["multipart/mixed", {"boundary": "199d7350597e43c0af0e4c814b8a35af"}]],    
["Mime-Version", "1.0"], 
["Subject", "Test Message"],
["From", "Test Sender <[email protected]>"],
["To", "Test Receiver <[email protected]>"],
["Reply-To", "[email protected]"], 
["Message-Id", "<[email protected]>"], 
["X-Mailgun-Sid", "WyIzOTUwOCIsICJuZWlsLmRvYnNvbkBleGFsdGdyb3VwLmNvbS5hdSIsICI4ZjY3OCJd"], 
["Date", "Fri, 14 Jun 2013 02:25:33 +0000"], 
["Sender", "[email protected]"]]

I assumed this would deserialize to a key/value pair list but i'm unable to get this working. Obviously the Content-Type item is more complex.

Can anyone help parse this to a list or poco using ServiceStack or built-in NET deserializers?

Upvotes: 4

Views: 2028

Answers (1)

Raul Nohea Goodness
Raul Nohea Goodness

Reputation: 2579

It's unfortunate the 3rd-party API returns the JSON in [["key","value"],...] arrays rather than {"key:"value", ...}. The latter would be much easier to parse into a typical class like this:

public class Foo
{
    public string Received {get; set;}
    [DataMember(Name = "Content-Type")]
    public string ContentType {get; set;}
    ... 
}

The way it returns is an anonymous list of values, containing more anonymous lists, where the 0 value is the key and the 1 value is the value.

I haven't tried it, but you may want to try deserializing to dynamic list of anonymous types, per this SO answer

List<JsonObject> jsonObject = JsonArrayObjects.Parse(json);
jsonObject.PrintDump(); // show data

Then for convenience, you could write a mapping routine to copy the jsonObject to a more readable class.

Update: i wrote a bit of code to test. Not that pretty, but it does work to access the parsed JSON as-is.

string json = @"[[""Received"", ""by luna.mailgun.net with SMTP mgrt 8765806286401; Fri, 14 Jun 2013 02:25:33 +0000""],
[""Content-Type"", [""multipart/mixed"", {""boundary"": ""199d7350597e43c0af0e4c814b8a35af""}]],    
[""Mime-Version"", ""1.0""], 
[""Subject"", ""Test Message""],
[""From"", ""Test Sender <[email protected]>""],
[""To"", ""Test Receiver <[email protected]>""],
[""Reply-To"", ""[email protected]""], 
[""Message-Id"", ""<[email protected]>""], 
[""X-Mailgun-Sid"", ""WyIzOTUwOCIsICJuZWlsLmRvYnNvbkBleGFsdGdyb3VwLmNvbS5hdSIsICI4ZjY3OCJd""], 
[""Date"", ""Fri, 14 Jun 2013 02:25:33 +0000""], 
[""Sender"", ""[email protected]""]]";

List<JsonObject> jsonObject = JsonArrayObjects.Parse(json);
// jsonObject.PrintDump(); // show data

string received = jsonObject[0].Values.First();
string contentType = jsonObject[1].Values.First();
List<JsonObject> contentTypeValues = JsonArrayObjects.Parse(jsonObject[1].Values.First());
string boundary = contentTypeValues[1].Values.First();
string mimeVersion = jsonObject[2].Values.First();

Console.WriteLine(string.Format("received: {0}", received));
Console.WriteLine(string.Format("contentType: {0}", contentType));
Console.WriteLine(string.Format("boundary: {0}", boundary));
Console.WriteLine(string.Format("mimeVersion: {0}", mimeVersion));

Upvotes: 3

Related Questions