Advertisement
Guest User

Untitled

a guest
Feb 2nd, 2012
738
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.50 KB | None | 0 0
  1. 109    class SimpleJSON
  2.     {
  3.         static Dictionary<string, string> res;
  4.         /// <summary>Парсим JSON строку (не простое число) и возвращаем одноуровневый список значений с именами полей, собираемые из имен json параметров и элементов массивов</summary>
  5.         /// <param name="str">json строка</param>
  6.         /// <returns>Возвращаем одноуровневый массив всех пар имя=>значение, где имя состоит из вложенных имен значений из json разделеных точками, например orders[0].amount=>10</returns>
  7.         static public Dictionary<string, string> pairsParseJSON(string str)
  8.         {
  9.             res = new Dictionary<string, string>();
  10.             SimpleJSON.parsePair(str.Trim(new char[]{'\n','\r','\t',' '}),0,0,"");
  11.             return res;
  12.         }
  13.         static int parsePair(string str, int pos,int lvl,string names)
  14.         {
  15.             int strlen = str.Length;
  16.             int idx = -1;
  17.             while (pos < strlen)
  18.             { // на кажэдом шаге мы начинаем либо с символов начала списка или объекта, либо с элемента списка, которвй в свою очередь либо элемент либо именованный элемент
  19.                 idx++;
  20.                 // пробелы и запятые
  21.                 while (pos < strlen && (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\n' || str[pos] == '\r' || str[pos] == ',')) pos++;
  22.                 // именованный параметр: "test":
  23.                 Regex re = new Regex("^\"(([^\"\\\\]+)(\\\\.[^\"\\\\]*)*)\" *: *");
  24.                 Match rm = re.Match(str.Substring(pos));
  25.                 string lname;
  26.                 if (!rm.Success)
  27.                 { // нет имени, значит это элемент массива, берем предыдущий, и прибавляем к нему 1, если это первый - имя равно 0
  28.                     // длинное имя
  29.                     lname = (names != "" ? names + "[" : "") + (lvl == 0 ? "" : idx.ToString()) + (names != "" ? "]" : "");
  30.                 }
  31.                 else
  32.                 {
  33.                     string name = rm.Groups[1].Value.Trim('"');
  34.                     pos += rm.Length;
  35.                     // длинное имя
  36.                     lname = (names != "" ? names + "." : "") + (lvl == 0 ? "" : name);
  37.                 }
  38.                 // пробелы
  39.                 while (pos < strlen && (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\n' || str[pos] == '\r')) pos++;
  40.                 // проверим начало списка или объекта {, [
  41.                 if (str[pos] == '{' || str[pos] == '[') { pos = SimpleJSON.parsePair(str, pos + 1, lvl + 1, lname); continue; }
  42.                 // проверим окончание списка ии объекта }, ]
  43.                 if (str[pos] == '}' || str[pos] == ']') return pos + 1;
  44.                 // простые значения
  45.                 if (str[pos] == '"') re = new Regex("\"([^\"\\\\]+(\\\\.[^\"\\\\]*)*)\""); else re = new Regex("([^, \\:}\\]]+)");
  46.                 rm = re.Match(str, pos);
  47.                 if (!rm.Success) return pos+1; // todo: обработать корректно ошибки
  48.                 res[lname] = rm.Value.Trim('"');
  49.                 pos += rm.Length;
  50.                 //
  51.             }
  52.             return pos;
  53.         }
  54.  
  55.         static public Dictionary<string, object> treeParseJSON(string str)
  56.         {
  57.             int pos = 0;
  58.             Dictionary<string, object> res = SimpleJSON.parseTree(str.Trim(new char[] { '\n', '\r', '\t', ' ' }), ref pos, 0);
  59.             if (res.Count == 1 && res.ContainsKey("0") && res["0"].GetType() == typeof(Dictionary<string, object>)) return (Dictionary<string, object>)res["0"];
  60.             return res;
  61.         }
  62.         /// <summary>Сканирует строку str в позиции pos на наличие элемента список-json ивозвращает в виде объекта tree</summary>
  63.         /// <param name="str"></param>
  64.         /// <param name="pos"></param>
  65.         /// <param name="lvl"></param>
  66.         /// <returns></returns>
  67.         static Dictionary<string, object> parseTree(string str, ref int pos, int lvl)
  68.         {
  69.             Dictionary<string, object> res = new Dictionary<string, object>();
  70.             int strlen = str.Length;
  71.             int idx = -1; // начинаем с 0, но так как шаг увеличивается в начале списка... то -1
  72.             while (pos < strlen)
  73.             { // на кажэдом шаге мы начинаем либо с символов начала списка или объекта, либо с элемента списка, которвй в свою очередь либо элемент либо именованный элемент
  74.                 idx++;
  75.                 // пробелы и запятые
  76.                 while (pos < strlen && (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\n' || str[pos] == '\r' || str[pos] == ',')) pos++;
  77.                 if (pos >= strlen) break;
  78.                 // именованный параметр: "test":
  79.                 Regex re = new Regex("^\"(([^\"\\\\]+)(\\\\.[^\"\\\\]*)*)\" *: *");
  80.                 Match rm = re.Match(str.Substring(pos));
  81.                 string name;
  82.                 if (!rm.Success)
  83.                 { // нет имени, значит это элемент массива
  84.                     // длинное имя
  85.                     name = idx.ToString();
  86.                 }
  87.                 else
  88.                 {
  89.                     name = rm.Groups[1].Value.Trim('"');
  90.                     pos += rm.Length;
  91.                 }
  92.                 // пробелы
  93.                 while (pos < strlen && (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\n' || str[pos] == '\r')) pos++;
  94.                 // проверим начало списка или объекта {, [
  95.                 if (str[pos] == '{' || str[pos] == '[') { pos++; res[name] = SimpleJSON.parseTree(str, ref pos, lvl + 1); continue; }
  96.                 // проверим окончание списка ии объекта }, ]
  97.                 if (str[pos] == '}' || str[pos] == ']') { pos++; return res; }
  98.                 // простые значения
  99.                 bool isNumber= true;
  100.                 if (str[pos] == '"') { re = new Regex("\"([^\"\\\\]*(\\\\.[^\"\\\\]*)*)\""); isNumber = false; } else re = new Regex("([^, \\:}\\]]+)");
  101.                 rm = re.Match(str, pos);
  102.                 if (!rm.Success) { pos++; return res; } // todo: обработать корректно ошибки
  103.                 if (isNumber && new Regex(@"^[0-9]+$").Match(rm.Value).Success) res[name] = Convert.ToInt64(rm.Value); else res[name] = rm.Value.Trim('"');
  104.                 pos += rm.Length;
  105.                 //
  106.             }
  107.             return res;
  108.         }
  109.         /// <summary>формируем строку json типа строка, обрамляя ковычками и подставляя коды символов \xXXXX</summary>
  110.         /// <param name="elem">строка</param>
  111.         /// <returns>строка в формате json</returns>
  112.         public static string str2json(string elem)
  113.         { // todo: сделать корректное преобразование для любых символов
  114.             return "\"" + elem.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n").Replace("\r", "\\r").Replace("\t", "\\t") + "\"";
  115.         }
  116.         /// <summary>формируем строку json на основе списка типа tree</summary>
  117.         /// <param name="tree">список, элементы либо dictionary<string,object> либо object</param>
  118.         /// <returns>строка в формате json</returns>
  119.         public static string makeJson(Dictionary<string,object> tree)
  120.         {
  121.             // определим, массив это или объект
  122.             int idx = 0;
  123.             bool isArray=true;
  124.             foreach (KeyValuePair<string, object> o in tree) if (o.Key != (idx++).ToString()) { isArray = false; break; }
  125.             if (isArray) return "[" + makeJsonList(tree,true) + "]"; else return "{" + makeJsonList(tree,false) + "}";
  126.         }
  127.         public static string makeJson(Dictionary<string, string> list)
  128.         {
  129.             Dictionary<string, object> tree = new Dictionary<string, object>();
  130.             foreach (KeyValuePair<string, string> o in list) tree.Add(o.Key, o.Value);
  131.             return makeJson(tree);
  132.         }
  133.         /// <summary>формируем строку, состояющую из элементов json через запятую</summary>
  134.         static string makeJsonList(Dictionary<string, object> tree,bool skipNames)
  135.         {
  136.             string res = "";
  137.             foreach (KeyValuePair<string, object> o in tree) if (o.Value.GetType() == typeof(Dictionary<string, object>))
  138.             { // другой список
  139.                 res += (res == "" ? "" : ", ") + (skipNames?"":SimpleJSON.str2json(o.Key)+":") + SimpleJSON.makeJson((Dictionary<string, object>)o.Value);
  140.             } else
  141.             { // простой элемент - число, строка
  142.                 if (o.Value.GetType() == typeof(double)
  143.                  || o.Value.GetType() == typeof(Double)
  144.                  || o.Value.GetType() == typeof(float)
  145.                  || o.Value.GetType() == typeof(int)
  146.                  || o.Value.GetType() == typeof(Int16)
  147.                  || o.Value.GetType() == typeof(Int32)
  148.                  || o.Value.GetType() == typeof(Int64)
  149.                  || o.Value.GetType() == typeof(long))
  150.                      res += (res == "" ? "" : ", ") + (skipNames ? "" : SimpleJSON.str2json(o.Key) + ":") + o.Value.ToString().Replace(',','.');
  151.                 else res += (res == "" ? "" : ", ") + (skipNames ? "" : SimpleJSON.str2json(o.Key) + ":") + SimpleJSON.str2json(o.Value.ToString());
  152.             }
  153.             return res;
  154.         }
  155.         public static double ConvertToDouble(string str)
  156.         {
  157.             return Convert.ToDouble(str.Replace(" ", "").Replace(".", NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator));
  158.         }
  159.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement