asp.net - How to convert hierarchical key value pairs from a string into json with c#? -
i have following http post body sent asp.net web api via web hook chargify.
id=38347752&event=customer_update&payload[customer][address]=qreweqwrerwq&payload[customer][address_2]=qwerewrqew&payload[customer][city]=ererwqqerw&payload[customer][country]=gb&payload[customer][created_at]=2015-05-14%2004%3a46%3a48%20-0400&payload[customer][email]=a%40test.com&payload[customer][first_name]=al&payload[customer][id]=8619620&payload[customer][last_name]=test&payload[customer][organization]=&payload[customer][phone]=01&payload[customer][portal_customer_created_at]=2015-05-14%2004%3a46%3a49%20-0400&payload[customer][portal_invite_last_accepted_at]=&payload[customer][portal_invite_last_sent_at]=2015-05-14%2004%3a46%3a49%20-0400&payload[customer][reference]=&payload[customer][state]=&payload[customer][updated_at]=2015-05-14%2011%3a25%3a19%20-0400&payload[customer][verified]=false&payload[customer][zip]=&payload[site][id]=26911&payload[site][subdomain]=testsubdomain how convert payload[customer][address]=value etc. json string using c#?
you current problem
how convert chargify webhooks json c#?
can generalized
how extract key value pairs string, convert them corresponding hierarchy , return them in json?
to answer question:
string rawdata = "id=38347752&event=customer_update&payload[customer][address]=qreweqwrerwq&payload[customer][address_2]=qwerewrqew&payload[customer][city]=ererwqqerw&payload[customer][country]=gb&payload[customer][created_at]=2015-05-14%2004%3a46%3a48%20-0400&payload[customer][email]=a%40test.com&payload[customer][first_name]=al&payload[customer][id]=8619620&payload[customer][last_name]=test&payload[customer][organization]=&payload[customer][phone]=01&payload[customer][portal_customer_created_at]=2015-05-14%2004%3a46%3a49%20-0400&payload[customer][portal_invite_last_accepted_at]=&payload[customer][portal_invite_last_sent_at]=2015-05-14%2004%3a46%3a49%20-0400&payload[customer][reference]=&payload[customer][state]=&payload[customer][updated_at]=2015-05-14%2011%3a25%3a19%20-0400&payload[customer][verified]=false&payload[customer][zip]=&payload[site][id]=26911&payload[site][subdomain]=testsubdomain"; chargifywebhook webhook = new chargifywebhook(rawdata); jsonnode node = new jsonnode("rootorwhatever"); foreach (keyvaluepair<string, string> keyvaluepair in webhook.keyvaluepairs) { node.insertinhierarchy(chargifywebhook.extracthierarchyfromkey(keyvaluepair.key), keyvaluepair.value); } string result = node.tojsonobject(); with specified input result looks (without line breaks):
{ "id": "38347752", "event": "customer_update", "payload": { "customer": { "address": "qreweqwrerwq", "address_2": "qwerewrqew", "city": "ererwqqerw", "country": "gb", "created_at": "2015-05-14 04:46:48 -0400", "email": "a@test.com", "first_name": "al", "id": "8619620", "last_name": "test", "organization": "", "phone": "01", "portal_customer_created_at": "2015-05-14 04:46:49 -0400", "portal_invite_last_accepted_at": "", "portal_invite_last_sent_at": "2015-05-14 04:46:49 -0400", "reference": "", "state": "", "updated_at": "2015-05-14 11:25:19 -0400", "verified": "false", "zip": "" }, "site": { "id": "26911", "subdomain": "testsubdomain" } } } as problem not limited 1, 2 or 3 levels need recursive solution. therefore created jsonnode class able insert children specifying hierarchy list<string>.
if take a.b.c example, @ beginning method insertintohierarchy checks whether more levels needed or not (depending on length of entries specified, in our case list containing a, b , c), if inserts child (used container) specified name of level , passes problem on child. of course name of current recursion level removed during step according our example container name a have been added , list containing b , c have been passed on container. if last level of recursion reached, node containing name , value inserted.
to solution working need following 2 classes:
chargifywebhook
/// <summary> /// represents chargify web hook class. /// </summary> public class chargifywebhook { /// <summary> /// indicates whether raw data has been parsed or not. /// </summary> private bool initialized; /// <summary> /// contains key value pairs extracted raw data. /// </summary> private dictionary<string, string> keyvaluepairs; /// <summary> /// initializes new instance of <see cref="chargifywebhook"/> class. /// </summary> /// <param name="data">the raw data of web hook.</param> /// <exception cref="system.argumentexception">is thrown if sepcified raw data null or empty.</exception> public chargifywebhook(string data) { if (string.isnullorempty(data)) { throw new argumentexception("the specified value must neither null nor empty", data); } this.initialized = false; this.keyvaluepairs = new dictionary<string, string>(); this.rawdata = data; } /// <summary> /// gets raw data of web hook. /// </summary> public string rawdata { get; private set; } /// <summary> /// gets key value pairs contained in raw data. /// </summary> public dictionary<string, string> keyvaluepairs { { if (!initialized) { this.keyvaluepairs = extractkeyvaluesfromrawdata(this.rawdata); initialized = true; } return this.keyvaluepairs; } } /// <summary> /// extracts key value pairs specified raw data. /// </summary> /// <param name="rawdata">the data contains key value pairs.</param> /// <param name="keyvaluepairseperator">the pair seperator, default '&'.</param> /// <param name="keyvalueseperator">the key value seperator, default '='.</param> /// <returns>the extracted key value pairs.</returns> /// <exception cref="system.formatexception">is thrown if key value seperator missing.</exception> public static dictionary<string, string> extractkeyvaluesfromrawdata(string rawdata, char keyvaluepairseperator = '&', char keyvalueseperator = '=') { dictionary<string, string> keyvaluepairs = new dictionary<string, string>(); string[] rawdataparts = rawdata.split(new char[] { keyvaluepairseperator }); foreach (string rawdatapart in rawdataparts) { string[] keyandvalue = rawdatapart.split(new char[] { keyvalueseperator }); if (keyandvalue.length != 2) { throw new formatexception("the format of specified raw data incorrect. key value pairs in following format expected: key=value or key1=value1&key2=value2..."); } keyvaluepairs.add(uri.unescapedatastring(keyandvalue[0]), uri.unescapedatastring(keyandvalue[1])); } return keyvaluepairs; } /// <summary> /// extracts hierarchy key, e.g. a[b][c] result in a, b , c. /// </summary> /// <param name="key">the key who's hierarchy shall extracted.</param> /// <param name="hierarchyopensequence">specifies open sequence hierarchy speration.</param> /// <param name="hierarchyclosesequence">specifies close sequence hierarchy speration.</param> /// <returns>a list of entries hierarchy names.</returns> public static list<string> extracthierarchyfromkey(string key, string hierarchyopensequence = "[", string hierarchyclosesequence = "]") { if (key.contains(hierarchyopensequence) && key.contains(hierarchyclosesequence)) { return key.replace(hierarchyclosesequence, string.empty).split(new string[] { hierarchyopensequence }, stringsplitoptions.none).tolist(); } if (key.contains(hierarchyopensequence) && !key.contains(hierarchyclosesequence)) { return key.split(new string[] { hierarchyopensequence }, stringsplitoptions.none).tolist(); } if (!key.contains(hierarchyopensequence) && key.contains(hierarchyclosesequence)) { return key.split(new string[] { hierarchyclosesequence }, stringsplitoptions.none).tolist(); } return new list<string>() { key }; } } jsonnode
/// <summary> /// represents jsonnode class. /// </summary> public class jsonnode { /// <summary> /// initializes new instance of <see cref="jsonnode"/> class. /// </summary> /// <param name="name">the name of node.</param> /// <param name="value">the value of node.</param> public jsonnode(string name, string value) { this.name = name; this.value = value; this.children = new dictionary<string, jsonnode>(); } /// <summary> /// initializes new instance of <see cref="jsonnode"/> class. /// </summary> /// <param name="name">the name of node.</param> public jsonnode(string name) : this(name, string.empty) { } /// <summary> /// gets name of node. /// </summary> public string name { get; private set; } /// <summary> /// gets children of node. /// </summary> public dictionary<string, jsonnode> children { get; private set; } /// <summary> /// gets value of node. /// </summary> public string value { get; private set; } /// <summary> /// inserts new node in corresponding hierarchy. /// </summary> /// <param name="keyhierarchy">a list entries specify hierarchy.</param> /// <param name="value">the value of node.</param> /// <exception cref="system.argumentnullexception">is thrown if keyhierarchy null.</exception> /// <exception cref="system.argumentexception">is thrown if keyhierarchy empty.</exception> public void insertinhierarchy(list<string> keyhierarchy, string value) { if (keyhierarchy == null) { throw new argumentnullexception("keyhierarchy"); } if (keyhierarchy.count == 0) { throw new argumentexception("the specified hierarchy list empty", "keyhierarchy"); } // if not in correct hierarchy (at last level), pass problem // child. if (keyhierarchy.count > 1) { // extract current hierarchy level key string key = keyhierarchy[0]; // if key not exists - add child. if (!this.children.containskey(key)) { this.children.add(key, new jsonnode(key)); } // remove current hierarchy list , ... keyhierarchy.removeat(0); // ... pass on inserted child. this.children[key].insertinhierarchy(keyhierarchy, value); return; } // if on last level, insert node it's value. this.children.add(keyhierarchy[0], new jsonnode(keyhierarchy[0], value)); } /// <summary> /// gets textual representation of node json entry. /// </summary> /// <returns>a textual representaiton of node json entry.</returns> public string tojsonentry() { // if there no child, return name , value in json format. if (this.children.count == 0) { return string.format("\"{0}\":\"{1}\"", this.name, this.value); } // otherwise there childs return of them formatted object. stringbuilder builder = new stringbuilder(); builder.appendformat("\"{0}\":", this.name); builder.append(this.tojsonobject()); return builder.tostring(); } /// <summary> /// gets textual representation of node json object. /// </summary> /// <returns>a textual representaiton of node json object.</returns> public string tojsonobject() { stringbuilder builder = new stringbuilder(); builder.append("{"); foreach (jsonnode value in this.children.values) { builder.append(value.tojsonentry()); builder.append(","); } builder.remove(builder.length - 1, 1); builder.append("}"); return builder.tostring(); } }
Comments
Post a Comment