Прикручивая авторизацию с помощью популярных сайтов, столкнулся с проблемой. Согласно стандарту 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