Mercurial > pub > ImplabNet
view Implab/JSON/JSONXmlReader.cs @ 58:1710dcda34bb
Added JSONXmlReader
author | cin |
---|---|
date | Tue, 17 Jun 2014 19:40:43 +0400 |
parents | |
children | 21611344d366 |
line wrap: on
line source
using Implab; using Implab.JSON; using Implab.Parsing; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; namespace ConsPlay { public class JSONXmlReader : XmlReader { enum ValueContext { Undefined, ElementStart, ElementValue, ElementEnd, ElementEmpty } struct LocalNameContext { public string localName; public bool isArray; } JSONParser m_parser; ValueContext m_valueContext; ReadState m_state = ReadState.Initial; Stack<LocalNameContext> m_localNameStack = new Stack<LocalNameContext>(); LocalNameContext m_localName; string m_rootName = "json"; string m_prefix = String.Empty; string m_namespaceUri = String.Empty; bool m_flattenArrays = false; NameTable m_nameTable = new NameTable(); int m_depthCorrection = 0; public JSONXmlReader(JSONParser parser) { Safe.ArgumentNotNull(parser, "parser"); m_parser = parser; } /// <summary> /// Always 0, JSON doesn't support attributes /// </summary> public override int AttributeCount { get { return 0; } } public override string BaseURI { get { return String.Empty; } } public override int Depth { get { return m_localNameStack.Count+m_depthCorrection; } } public override bool EOF { get { return m_parser.EOF; } } /// <summary> /// Always throws an exception /// </summary> /// <param name="i"></param> /// <returns></returns> public override string GetAttribute(int i) { throw new ArgumentOutOfRangeException(); } /// <summary> /// Always returns empty string /// </summary> /// <param name="name"></param> /// <param name="namespaceURI"></param> /// <returns></returns> public override string GetAttribute(string name, string namespaceURI) { return String.Empty; } /// <summary> /// Always returns empty string /// </summary> /// <param name="name"></param> /// <returns></returns> public override string GetAttribute(string name) { return String.Empty; } public override bool IsEmptyElement { get { return m_parser.ElementType == JSONElementType.Value && m_valueContext == ValueContext.ElementEmpty; } } public override string LocalName { get { return m_localName.localName; } } public override string LookupNamespace(string prefix) { if (String.IsNullOrEmpty(prefix) || prefix == m_prefix) return m_namespaceUri; else return String.Empty; } public override bool MoveToAttribute(string name, string ns) { return false; } public override bool MoveToAttribute(string name) { return false; } public override bool MoveToElement() { return false; } public override bool MoveToFirstAttribute() { return false; } public override bool MoveToNextAttribute() { return false; } public override XmlNameTable NameTable { get { return m_nameTable; } } public override string NamespaceURI { get { return m_namespaceUri; } } public override XmlNodeType NodeType { get { switch (m_parser.ElementType) { case JSONElementType.BeginObject: case JSONElementType.BeginArray: return XmlNodeType.Element; case JSONElementType.EndObject: case JSONElementType.EndArray: return XmlNodeType.EndElement; case JSONElementType.Value: switch (m_valueContext) { case ValueContext.ElementStart: case ValueContext.ElementEmpty: return XmlNodeType.Element; case ValueContext.ElementValue: return XmlNodeType.Text; case ValueContext.ElementEnd: return XmlNodeType.EndElement; default: throw new InvalidOperationException(); } default: throw new InvalidOperationException(); } } } public override string Prefix { get { return m_prefix; } } public override bool Read() { if (m_state != System.Xml.ReadState.Interactive && m_state != System.Xml.ReadState.Initial) return false; if (m_state == ReadState.Initial) m_state = System.Xml.ReadState.Interactive; try { switch (m_parser.ElementType) { case JSONElementType.Value: switch (m_valueContext) { case ValueContext.ElementStart: SetLocalName(String.Empty); m_valueContext = ValueContext.ElementValue; return true; case ValueContext.ElementValue: RestoreLocalName(); m_valueContext = ValueContext.ElementEnd; return true; case ValueContext.ElementEmpty: case ValueContext.ElementEnd: RestoreLocalName(); break; } break; case JSONElementType.EndArray: case JSONElementType.EndObject: RestoreLocalName(); break; } string itemName = m_parser.ElementType == JSONElementType.None ? m_rootName : m_flattenArrays ? m_localName.localName : "item"; while (m_parser.Read()) { if (!String.IsNullOrEmpty(m_parser.ElementName)) itemName = m_parser.ElementName; switch (m_parser.ElementType) { case JSONElementType.BeginArray: if (m_flattenArrays && !m_localName.isArray) { m_depthCorrection--; SetLocalName(itemName, true); continue; } else { SetLocalName(itemName, true); } break; case JSONElementType.BeginObject: SetLocalName(itemName); break; case JSONElementType.EndArray: if (m_flattenArrays && !m_localNameStack.Peek().isArray) { RestoreLocalName(); m_depthCorrection++; continue; } break; case JSONElementType.EndObject: break; case JSONElementType.Value: SetLocalName(itemName); m_valueContext = m_parser.ElementValue == null ? ValueContext.ElementEmpty : ValueContext.ElementStart; break; default: break; } return true; } m_state = System.Xml.ReadState.EndOfFile; return false; } catch { m_state = System.Xml.ReadState.Error; throw; } } public override bool ReadAttributeValue() { return false; } public override ReadState ReadState { get { return m_state; } } public override void ResolveEntity() { // do nothing } public override string Value { get { return m_parser.ElementValue == null ? String.Empty : m_parser.ElementValue.ToString(); } } void SetLocalName(string name) { m_localNameStack.Push(m_localName); m_localName.localName = name; m_localName.isArray = false; } void SetLocalName(string name, bool isArray) { m_localNameStack.Push(m_localName); m_localName.localName = name; m_localName.isArray = isArray; } void RestoreLocalName() { m_localName = m_localNameStack.Pop(); } public override void Close() { m_state = System.Xml.ReadState.EndOfFile ; } } }