Парсинг Json на C#

в 15:43, , рубрики: .net, ASP, C#, C# Json OAuth, метки:

imageПрикручивая авторизацию с помощью популярных сайтов, столкнулся с проблемой. Согласно стандарту OAuth, ответ от сервера авторизации приходит в формате Json, а в .net удобной функции для его парсинга нет. Существует, конечно, JavaScriptSerializer, но он наследует все проблемы сериализеров. Во-первых, если будет расхождение в названии полей, тогда будут появляться исключения. Во-вторых, чисто лень создавать класс, пусть и содержащий только название полей под каждый ответ. Я подключал 8 систем авторизации, в среднем мне пришлось бы написать по 2-3 класса на каждую. То есть где-то 20 классов. Я уже не говорю о тех, кто делает глубокую интеграцию. Зачем нагромождать код? Ну и, естественно, в вебе особо остро стоит вопрос производительности, а сериализаторы производительностью не блещут. Исходя из всех этих рассуждений я написал довольно простую функцию, которая превращает строку json в словарь типа Dictionary<string,string>.

        static Dictionary<string, string> ParseJson(string res)
        {
            var lines = res.Split("rn".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            var ht = new Dictionary<string, string>(20);
            var st = new Stack<string>(20);

            for (int i = 0; i < lines.Length; ++i)
            {
                var line = lines[i];
                var pair = line.Split(":".ToCharArray(), 2, StringSplitOptions.RemoveEmptyEntries);

                if (pair.Length == 2)
                {
                    var key = ClearString(pair[0]);
                    var val = ClearString(pair[1]);

                    if (val == "{")
                    {
                        st.Push(key);
                    }
                    else
                    {
                        if (st.Count > 0)
                        {
                            key = string.Join("_", st) + "_" + key;
                        }

                        if (ht.ContainsKey(key))
                        {
                            ht[key] += "&" + val;
                        }
                        else
                        {
                            ht.Add(key, val);
                        }
                    }
                }
                else if (line.IndexOf('}') != -1 && st.Count > 0)
                {
                    st.Pop();
                }
            }

            return ht;
        }

        static string ClearString(string str)
        {
            str = str.Trim();

            var ind0 = str.IndexOf(""");
            var ind1 = str.LastIndexOf(""");
            
            if (ind0 != -1 && ind1 != -1)
            {
                str = str.Substring(ind0 + 1, ind1 - ind0 - 1);
            }
            else if (str[str.Length-1] == ',')
            {
                str = str.Substring(0, str.Length - 1);
            }

            str = HttpUtility.UrlDecode(str);

            return str;
        }

Рассмотрим пример json строки полученной от системы Windows LiveId:

{
   "id": "cb6e111111aaaaaa", 
   "name": "Code Tester", 
   "first_name": "Code", 
   "last_name": "Tester", 
   "link": "http://profile.live.com/cid-cb6e111111aaaaaa/", 
   "gender": "male", 
   "emails": {
      "preferred": "tester@gmail.com", 
      "account": "tester@gmail.com", 
      "personal": null, 
      "business": null
   }, 
   "locale": "en_US", 
   "updated_time": "2012-05-21T21:40:43+0000"
}

Превращается в словарь:

id,                 cb6e111111aaaaaa
name,               Code Tester
first_name,         Code
last_name,          Tester
link,               http://profile.live.com/cid-cb6e111111aaaaaa/
gender,             male
emails_preferred,   tester@gmail.com
emails_account,     tester@gmail.com
emails_personal,    null
emails_business,    null
locale,             en_US
updated_time,       2012-05-21T21:40:43+0000

Есть некоторые нюансы. Как видно из примера, вложенные объекты получают префикс родителя. Таким образом, мы получили emails_preferred и emails_account. Если же json будет содержать массив объектов, тогда значения будут разделены символом &.

Надеюсь пригодится.

Автор: Master_Dante

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js