如何使用c#将字符串中的分层键值对转换为json?
我通过chargify的web钩子将以下http post正文发送到asp.net web api如何使用c#将字符串中的分层键值对转换为json?,c#,asp.net,json,chargify,C#,Asp.net,Json,Chargify,我通过chargify的web钩子将以下http post正文发送到asp.net web api id=38347752&event=customer_update&payload[customer][address]=qreweqwrerwq&payload[customer][address_2]=qwerewrqew&payload[customer][city]=ererwqqerw&payload[customer][country]=GB&a
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
如何使用c#将有效负载[customer][address]=值等转换为json字符串?您当前的问题
如何使用c#将chargify Webhook转换为json
可以推广到
如何从字符串中提取键值对,将其转换为相应的层次结构并以JSON格式返回?
回答你的问题:
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();
由于您的问题不限于1、2或3个级别,您显然需要递归解决方案。因此,我创建了一个JSONNode
类,它可以通过将层次结构指定为列表来插入子级
如果以A.B.C
为例,开始时方法InsertIntoHierarchy
检查是否需要更多级别(取决于指定条目的长度,在本例中,我们将得到一个包含A
、B
和C
)的列表,如果需要,则插入一个子级(用作容器)使用指定的级别的名称,并将问题传递给该子级。当然,当前递归级别的名称在该步骤中被删除,因此根据我们的示例,具有名称A
的容器将被添加,并且包含B
和C
的列表将被传递到此容器。如果达到递归的最后一级,将插入包含名称
和值
的节点
要使解决方案发挥作用,您需要以下两个类:
ChargifyWebHook
/// <summary>
/// Represents the chargify web hook class.
/// </summary>
public class ChargifyWebHook
{
/// <summary>
/// Indicates whether the raw data has already been parsed or not.
/// </summary>
private bool initialized;
/// <summary>
/// Contains the key value pairs extracted from the raw data.
/// </summary>
private Dictionary<string, string> keyValuePairs;
/// <summary>
/// Initializes a new instance of the <see cref="ChargifyWebHook"/> class.
/// </summary>
/// <param name="data">The raw data of the web hook.</param>
/// <exception cref="System.ArgumentException">Is thrown if the sepcified raw data is null or empty.</exception>
public ChargifyWebHook(string data)
{
if (String.IsNullOrEmpty(data))
{
throw new ArgumentException("The specified value must neither be null nor empty", data);
}
this.initialized = false;
this.keyValuePairs = new Dictionary<string, string>();
this.RawData = data;
}
/// <summary>
/// Gets the raw data of the web hook.
/// </summary>
public string RawData
{
get;
private set;
}
/// <summary>
/// Gets the key value pairs contained in the raw data.
/// </summary>
public Dictionary<string, string> KeyValuePairs
{
get
{
if (!initialized)
{
this.keyValuePairs = ExtractKeyValuesFromRawData(this.RawData);
initialized = true;
}
return this.keyValuePairs;
}
}
/// <summary>
/// Extracts the key value pairs from the specified raw data.
/// </summary>
/// <param name="rawData">The data which contains the key value pairs.</param>
/// <param name="keyValuePairSeperator">The pair seperator, default is '&'.</param>
/// <param name="keyValueSeperator">The key value seperator, default is '='.</param>
/// <returns>The extracted key value pairs.</returns>
/// <exception cref="System.FormatException">Is thrown if an key value seperator is 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 the specified raw data is incorrect. Key value pairs in the following format expected: key=value or key1=value1&key2=value2...");
}
keyValuePairs.Add(Uri.UnescapeDataString(keyAndValue[0]), Uri.UnescapeDataString(keyAndValue[1]));
}
return keyValuePairs;
}
/// <summary>
/// Extracts the hierarchy from the key, e.g. A[B][C] will result in A, B and C.
/// </summary>
/// <param name="key">The key who's hierarchy shall be extracted.</param>
/// <param name="hierarchyOpenSequence">Specifies the open sequence for the hierarchy speration.</param>
/// <param name="hierarchyCloseSequence">Specifies the close sequence for the hierarchy speration.</param>
/// <returns>A list of entries for the 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 };
}
}
//
///表示chargify web钩子类。
///
公共类ChargifyWebHook
{
///
///指示是否已分析原始数据。
///
私有布尔初始化;
///
///包含从原始数据中提取的键值对。
///
私有字典键值对;
///
///初始化类的新实例。
///
///web钩子的原始数据。
///如果指定的原始数据为null或空,则引发。
公共ChargifyWebHook(字符串数据)
{
if(String.IsNullOrEmpty(数据))
{
抛出新ArgumentException(“指定的值既不能为null也不能为空”,data);
}
this.initialized=false;
this.keyValuePairs=新字典();
this.RawData=数据;
}
///
///获取web钩子的原始数据。
///
公共字符串原始数据
{
得到;
私人设置;
}
///
///获取原始数据中包含的键值对。
///
公共字典键值对
{
得到
{
如果(!已初始化)
{
this.keyValuePairs=从RawData中提取keyValues(this.RawData);
初始化=真;
}
返回此.keyValuePairs;
}
}
///
///从指定的原始数据中提取键值对。
///
///包含键值对的数据。
///成对分隔符,默认值为“&”。
///键值分隔符,默认值为“=”。
///提取的键值对。
///如果缺少键值分隔符,则引发。
公共静态字典从rawData提取KeyValues(字符串rawData,char keyValuePairSeperator='&',char KeyValueSeparator='='='))
{
Dictionary keyValuePairs=新字典();
字符串[]rawDataParts=rawData.Split(新字符[]{keyvaluepairseroperator});
foreach(rawDataParts中的字符串rawDataPart)
{
字符串[]keyAndValue=rawDataPart.Split(新字符[]{keyValueSeparator});
如果(keyAndValue.Length!=2)
{
抛出新FormatException(“指定原始数据的格式不正确。需要以下格式的键值对:Key=value或key1=value1&key2=value2…”);
}
Add(Uri.UnescapeDataString(keyAndValue[0]),Uri.UnescapeDataString(keyAndValue[1]);
}
返回键值对;
}
///
///从键中提取层次结构,例如A[B][C]将产生A、B和C。
///
///应提取关键谁的层次结构。
///指定层次结构说明的打开顺序。
///指定层次结构说明的关闭顺序。
///层次结构名称的条目列表。
公共静态列表提取器HierarchyFromKey(字符串键,字符串hierarchyOpenSequence=“[”,字符串hierarchyCloseSequence=“]”)
{
if(key.Contains(hierarchyOpenSequence)和&key.Contains(hierarchyCloseSequence))
{
return key.Replace(hierarchyCloseSequence,string.Empty).Split(新字符串[]{hierarchyOpenSequence},StringSplitOptions.None).ToList();
}
if(key.Contains(hierarchyOpenSequence)和&!key.Contains(hierarchyCloseSequence))
{
return key.Split(新字符串[]{hierarchyOpenSequence},StringSplitOptions.None);
}
如果(!key.Contains(hierarchyOpenSequence)和&key.Contains(hierarchyCloseSequence))
{
return key.Split(新字符串[]{hierarchyclosesesequence},StringSplitOptions.None).ToList();
}
返回新列表(){key};
}
}
JSONNode
/// <summary>
/// Represents the JSONNode class.
/// </summary>
public class JSONNode
{
/// <summary>
/// Initializes a new instance of the <see cref="JSONNode"/> class.
/// </summary>
/// <param name="name">The name of the node.</param>
/// <param name="value">The value of the node.</param>
public JSONNode(string name, string value)
{
this.Name = name;
this.Value = value;
this.Children = new Dictionary<string, JSONNode>();
}
/// <summary>
/// Initializes a new instance of the <see cref="JSONNode"/> class.
/// </summary>
/// <param name="name">The name of the node.</param>
public JSONNode(string name)
: this(name, string.Empty)
{
}
/// <summary>
/// Gets the name of the node.
/// </summary>
public string Name
{
get;
private set;
}
/// <summary>
/// Gets the children of the node.
/// </summary>
public Dictionary<string, JSONNode> Children
{
get;
private set;
}
/// <summary>
/// Gets the value of the node.
/// </summary>
public string Value
{
get;
private set;
}
/// <summary>
/// Inserts a new node in the corresponding hierarchy.
/// </summary>
/// <param name="keyHierarchy">A list with entries who specify the hierarchy.</param>
/// <param name="value">The value of the node.</param>
/// <exception cref="System.ArgumentNullException">Is thrown if the keyHierarchy is null.</exception>
/// <exception cref="System.ArgumentException">Is thrown if the keyHierarchy is 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 is empty", "keyHierarchy");
}
// If we are not in the correct hierarchy (at the last level), pass the problem
// to the child.
if (keyHierarchy.Count > 1)
{
// Extract the current hierarchy level as key
string key = keyHierarchy[0];
// If the key does not already exists - add it as a child.
if (!this.Children.ContainsKey(key))
{
this.Children.Add(key, new JSONNode(key));
}
// Remove the current hierarchy from the list and ...
keyHierarchy.RemoveAt(0);
// ... pass it on to the just inserted child.
this.Children[key].InsertInHierarchy(keyHierarchy, value);
return;
}
// If we are on the last level, just insert the node with it's value.
this.Children.Add(keyHierarchy[0], new JSONNode(keyHierarchy[0], value));
}
/// <summary>
/// Gets the textual representation of this node as JSON entry.
/// </summary>
/// <returns>A textual representaiton of this node as JSON entry.</returns>
public string ToJSONEntry()
{
// If there is no child, return the name and the value in JSON format.
if (this.Children.Count == 0)
{
return string.Format("\"{0}\":\"{1}\"", this.Name, this.Value);
}
// Otherwise there are childs so return all of them formatted as object.
StringBuilder builder = new StringBuilder();
builder.AppendFormat("\"{0}\":", this.Name);
builder.Append(this.ToJSONObject());
return builder.ToString();
}
/// <summary>
/// Gets the textual representation of this node as JSON object.
/// </summary>
/// <returns>A textual representaiton of this node as 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();
}
}
//
///表示JSONNode类。
///
公共类JSONNode
{
///
///初始化类的新实例。
///
///节点的名称。
///节点的值。
公共JSONNode(字符串名称、字符串值)
{
this.Name=Name;
这个。值=值;
this.Children=新字典();
}
///
///初始化类的新实例。
///
///节点的名称。
公共JSONNode(字符串名称)
/// <summary>
/// Represents the JSONNode class.
/// </summary>
public class JSONNode
{
/// <summary>
/// Initializes a new instance of the <see cref="JSONNode"/> class.
/// </summary>
/// <param name="name">The name of the node.</param>
/// <param name="value">The value of the node.</param>
public JSONNode(string name, string value)
{
this.Name = name;
this.Value = value;
this.Children = new Dictionary<string, JSONNode>();
}
/// <summary>
/// Initializes a new instance of the <see cref="JSONNode"/> class.
/// </summary>
/// <param name="name">The name of the node.</param>
public JSONNode(string name)
: this(name, string.Empty)
{
}
/// <summary>
/// Gets the name of the node.
/// </summary>
public string Name
{
get;
private set;
}
/// <summary>
/// Gets the children of the node.
/// </summary>
public Dictionary<string, JSONNode> Children
{
get;
private set;
}
/// <summary>
/// Gets the value of the node.
/// </summary>
public string Value
{
get;
private set;
}
/// <summary>
/// Inserts a new node in the corresponding hierarchy.
/// </summary>
/// <param name="keyHierarchy">A list with entries who specify the hierarchy.</param>
/// <param name="value">The value of the node.</param>
/// <exception cref="System.ArgumentNullException">Is thrown if the keyHierarchy is null.</exception>
/// <exception cref="System.ArgumentException">Is thrown if the keyHierarchy is 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 is empty", "keyHierarchy");
}
// If we are not in the correct hierarchy (at the last level), pass the problem
// to the child.
if (keyHierarchy.Count > 1)
{
// Extract the current hierarchy level as key
string key = keyHierarchy[0];
// If the key does not already exists - add it as a child.
if (!this.Children.ContainsKey(key))
{
this.Children.Add(key, new JSONNode(key));
}
// Remove the current hierarchy from the list and ...
keyHierarchy.RemoveAt(0);
// ... pass it on to the just inserted child.
this.Children[key].InsertInHierarchy(keyHierarchy, value);
return;
}
// If we are on the last level, just insert the node with it's value.
this.Children.Add(keyHierarchy[0], new JSONNode(keyHierarchy[0], value));
}
/// <summary>
/// Gets the textual representation of this node as JSON entry.
/// </summary>
/// <returns>A textual representaiton of this node as JSON entry.</returns>
public string ToJSONEntry()
{
// If there is no child, return the name and the value in JSON format.
if (this.Children.Count == 0)
{
return string.Format("\"{0}\":\"{1}\"", this.Name, this.Value);
}
// Otherwise there are childs so return all of them formatted as object.
StringBuilder builder = new StringBuilder();
builder.AppendFormat("\"{0}\":", this.Name);
builder.Append(this.ToJSONObject());
return builder.ToString();
}
/// <summary>
/// Gets the textual representation of this node as JSON object.
/// </summary>
/// <returns>A textual representaiton of this node as 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();
}
}