private static bool FromJson(string s, bool canThrowException, out object result, out string remain) { try { s = s.TrimStart(); if (s == "") { throw new Exception("Empty value"); } if (s[0] == '[') { s = s.Substring(1).TrimStart(); Json a = new Json(); a.InitAsArray(); for (;;) { if (s[0] == ']') { break; } object v; FromJson(s, canThrowException, out v, out s); a.Append(v); s = s.TrimStart(); if (s[0] == ',') { s = s.Substring(1).TrimStart(); } } result = a; remain = s.Substring(1).TrimStart(); return(true); } else if (s[0] == '{') { s = s.Substring(1).TrimStart(); Json a = new Json(); a.InitAsDictionary(); for (;;) { if (s[0] == '}') { break; } object k; FromJson(s, canThrowException, out k, out s); s = s.TrimStart(); if (s[0] == ':') { s = s.Substring(1).TrimStart(); object v; FromJson(s, canThrowException, out v, out s); a.SetKey(k as string, v); s = s.TrimStart(); if (s[0] == ',') { s = s.Substring(1).TrimStart(); } } else { throw new Exception("Syntax error"); } } result = a; remain = s.Substring(1).TrimStart(); return(true); } else { // Direct value bool inQuote = false; int i = 0; for (i = 0; i < s.Length + 1; i++) { char ch = (char)0; if (i < s.Length) { ch = s[i]; } if (inQuote) { if ((ch == '\"') && ((i == 0) || (s[i - 1] != '\\'))) { inQuote = false; } } else { if ((ch == '\"') && ((i == 0) || (s[i - 1] != '\\'))) { inQuote = true; } else if ((ch == (char)0) || (ch == ',') || (ch == ':') || (ch == '}') || (ch == ']')) { // Valore singolo string value = s.Substring(0, i).Trim(); if ((value.StartsWith("\"")) && (value.EndsWith("\""))) { result = DecodeString(value.Substring(1, value.Length - 2)); remain = s.Substring(i); return(true); } if (value == "null") { result = null; remain = s.Substring(i); return(true); } if (value == "true") { result = true; remain = s.Substring(i); return(true); } if (value == "false") { result = false; remain = s.Substring(i); return(true); } int dI = 0; if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out dI)) { result = dI; remain = s.Substring(i); return(true); } double dD = 0; if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out dD)) { result = dD; remain = s.Substring(i); return(true); } throw new Exception("Cannot detect type of value '" + value + "'"); } } } throw new Exception("Syntax error"); } } catch (Exception e) { if (canThrowException) { throw new Exception("JsonParser:" + e.Message); } } result = null; remain = s; return(false); }
public static Json ToJson(XmlElement xml) { /* * Comments are ignored. * Node renames in json conversion can be forced with attribute json-convert-name. * Key name are lowered-case. * * Can fail if: * 1- There are duplicate child names. Example: * <test> * <alfa/> * <beta/> * <alfa/> * </test> * If all childs have the same name, works (detected as Array) * * 2- There are nested texts. Example: * <test> * mytext1 * <alfa/> * mytext2 * </test> * */ Json result = new Json(); foreach (XmlAttribute attr in xml.Attributes) { string keyName = attr.Name.ToLowerInvariant(); if (keyName.StartsWith("json-convert-")) { continue; } // Try Cast? if (result.HasKey(keyName)) { throw new Exception("Cannot convert."); } object value = attr.Value; if (attr.Value.ToLowerInvariant() == "true") { value = true; } else if (attr.Value.ToLowerInvariant() == "true") { value = false; } result.SetKey(keyName, value); } // Exception: if not have attributes, and childs are XmlElement with all the same name, use Json Array. bool isArray = false; if (xml.Attributes.Count == 0) { isArray = true; string commonName = ""; int nChildsWithName = 0; // Not really used yet foreach (XmlNode child in xml.ChildNodes) { if (child is XmlComment) { // Ignore } else if (child is XmlText) { // No Array isArray = false; break; } else if (child is XmlElement) { XmlElement xmlElement = child as XmlElement; string keyName = child.Name.ToLowerInvariant(); if (xmlElement.HasAttribute("json-convert-name")) { keyName = xmlElement.GetAttribute("json-convert-name"); } if (commonName == "") { commonName = keyName; } else if (commonName != keyName) { // No Array isArray = false; break; } nChildsWithName++; } else { throw new Exception("Xml node unknown type"); } } } foreach (XmlNode child in xml.ChildNodes) { if (child is XmlComment) { // Ignore } else if (child is XmlText) { /* * if (result.HasKey(child.ParentNode.Name)) * throw new Exception("Cannot convert."); * result.SetKey(child.ParentNode.Name, child.InnerText); */ } else if (child is XmlElement) { XmlElement xmlChild = child as XmlElement; // Exception: if contain text bool textFound = false; foreach (XmlNode xmlChild2 in xmlChild.ChildNodes) { if (xmlChild2 is XmlText) { result.SetKey(xmlChild.Name.ToLowerInvariant(), xmlChild.InnerText); textFound = true; break; } } if (textFound) { continue; } // Exception: if have only two attribute 'name' and 'value' if ((xmlChild.Attributes.Count == 2) && (xmlChild.HasAttribute("name")) && (xmlChild.HasAttribute("value"))) { if (result.HasKey(xmlChild.GetAttribute("name"))) { throw new Exception("Cannot convert."); } result.SetKey(xmlChild.GetAttribute("name").ToLowerInvariant(), xmlChild.GetAttribute("value")); } else { XmlElement xmlElement = child as XmlElement; string keyName = child.Name.ToLowerInvariant(); if (xmlElement.HasAttribute("json-convert-name")) { keyName = xmlElement.GetAttribute("json-convert-name"); } if ((isArray == false) && (result.HasKey(keyName))) { throw new Exception("Cannot convert."); } Json jChild = ToJson(xmlElement); if (isArray) { result.Append(jChild); } else { result.SetKey(keyName, jChild); } } } else { throw new Exception("Xml node unknown type"); } } return(result); }