2

我通过 chargify 的 web 挂钩将以下 http 帖子正文发送到了 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# 将此有效负载 [客户] [地址] = 值等转换为 json 字符串?

4

1 回答 1

0

你当前的问题

如何使用 c# 将 chargify webhooks 转换为 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();

使用您指定的输入,结果如下所示(没有换行符):

{
    "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"
                               }
               }
}

由于您的问题不限于 1、2 或 3 个级别,您显然需要递归解决方案。因此,我创建了一个JSONNode类,它可以通过将层次结构指定为List<string>.

A.B.C个例子,在开始的时候,该方法InsertIntoHierarchy会检查是否需要更多级别(取决于指定条目的长度,在我们的例子中,我们会得到一个包含A,B和的列表C),如果是这样,它会插入一个子 (用作容器)具有指定name的级别并将问题传递给该子级。当然,当前递归级别的名称在该步骤中被删除,因此根据我们的示例,将添加带有 的容器,并且将包含和name A的列表传递给该容器。如果达到最后一级递归,将插入一个包含和 的节点。BCnamevalue

要使解决方案正常工作,您将需要以下 2 个类:

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 };
    }
}

JSON节点

/// <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();
    }
}
于 2015-05-15T20:49:03.590 回答