Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用c#将字符串中的分层键值对转换为json?_C#_Asp.net_Json_Chargify - Fatal编程技术网

如何使用c#将字符串中的分层键值对转换为json?

如何使用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

我通过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&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();
    }
}