##// END OF EJS Templates
small refactoring
cin -
r64:a809805210d1 default
parent child
Show More
@@ -1,322 +1,324
1 1 using Implab;
2 2 using Implab.Parsing;
3 3 using System;
4 4 using System.Collections.Generic;
5 5 using System.Globalization;
6 6 using System.IO;
7 7 using System.Linq;
8 8 using System.Text;
9 9 using System.Threading.Tasks;
10 10 using System.Xml;
11 11
12 12 namespace Implab.JSON {
13 13 public class JSONXmlReader : XmlReader {
14 14
15 15 enum ValueContext {
16 16 Undefined,
17 17 ElementStart,
18 18 ElementValue,
19 19 ElementEnd,
20 20 ElementEmpty
21 21 }
22 22
23 23 struct LocalNameContext {
24 24 public string localName;
25 25 public bool isArray;
26 26 }
27 27
28 28 JSONParser m_parser;
29 29 ValueContext m_valueContext;
30 30 ReadState m_state = ReadState.Initial;
31 31 Stack<LocalNameContext> m_localNameStack = new Stack<LocalNameContext>();
32 32 LocalNameContext m_localName;
33 33 int m_depthCorrection = 0;
34 34
35 35 readonly string m_rootName;
36 36 readonly string m_prefix;
37 37 readonly string m_namespaceUri;
38 38 readonly bool m_flattenArrays;
39 39 readonly string m_arrayItemName;
40 40 readonly XmlNameTable m_nameTable;
41 readonly bool m_disposeParser;
42 41
43 public JSONXmlReader(JSONParser parser, JSONXmlReaderOptions options) {
44 Safe.ArgumentNotNull(parser, "parser");
42 JSONXmlReader(JSONParser parser, JSONXmlReaderOptions options) {
45 43 m_parser = parser;
46 44
47 45 if (options != null) {
48 46 m_prefix = options.NodesPrefix ?? String.Empty;
49 47 m_namespaceUri = options.NamespaceURI ?? String.Empty;
50 48 m_rootName = options.RootName ?? "json";
51 49 m_flattenArrays = options.FlattenArrays;
52 50 m_arrayItemName = options.ArrayItemName ?? "item";
53 51 m_nameTable = options.NameTable ?? new NameTable();
54 m_disposeParser = options.DisposeParser;
55 52 } else {
56 53 m_prefix = String.Empty;
57 54 m_namespaceUri = String.Empty;
58 55 m_rootName = "json";
59 56 m_flattenArrays = false;
60 57 m_arrayItemName = "item";
61 58 m_nameTable = new NameTable();
62 m_disposeParser = false;
63 59 }
64 60 }
65 61
66 62 /// <summary>
67 63 /// Always 0, JSON doesn't support attributes
68 64 /// </summary>
69 65 public override int AttributeCount {
70 66 get { return 0; }
71 67 }
72 68
73 69 public override string BaseURI {
74 70 get { return String.Empty; }
75 71 }
76 72
77 73 public override int Depth {
78 74 get {
79 75 return m_localNameStack.Count + m_depthCorrection;
80 76 }
81 77 }
82 78
83 79 public override bool EOF {
84 80 get { return m_parser.EOF; }
85 81 }
86 82
87 83 /// <summary>
88 84 /// Always throws an exception
89 85 /// </summary>
90 86 /// <param name="i"></param>
91 87 /// <returns></returns>
92 88 public override string GetAttribute(int i) {
93 89 throw new ArgumentOutOfRangeException();
94 90 }
95 91
96 92 /// <summary>
97 93 /// Always returns empty string
98 94 /// </summary>
99 95 /// <param name="name"></param>
100 96 /// <param name="namespaceURI"></param>
101 97 /// <returns></returns>
102 98 public override string GetAttribute(string name, string namespaceURI) {
103 99 return String.Empty;
104 100 }
105 101
106 102 /// <summary>
107 103 /// Always returns empty string
108 104 /// </summary>
109 105 /// <param name="name"></param>
110 106 /// <returns></returns>
111 107 public override string GetAttribute(string name) {
112 108 return String.Empty;
113 109 }
114 110
115 111 public override bool IsEmptyElement {
116 112 get { return m_parser.ElementType == JSONElementType.Value && m_valueContext == ValueContext.ElementEmpty; }
117 113 }
118 114
119 115 public override string LocalName {
120 116 get { return m_localName.localName; }
121 117 }
122 118
123 119 public override string LookupNamespace(string prefix) {
124 120 if (String.IsNullOrEmpty(prefix) || prefix == m_prefix)
125 121 return m_namespaceUri;
126 122 else
127 123 return String.Empty;
128 124 }
129 125
130 126 public override bool MoveToAttribute(string name, string ns) {
131 127 return false;
132 128 }
133 129
134 130 public override bool MoveToAttribute(string name) {
135 131 return false;
136 132 }
137 133
138 134 public override bool MoveToElement() {
139 135 return false;
140 136 }
141 137
142 138 public override bool MoveToFirstAttribute() {
143 139 return false;
144 140 }
145 141
146 142 public override bool MoveToNextAttribute() {
147 143 return false;
148 144 }
149 145
150 146 public override XmlNameTable NameTable {
151 147 get { return m_nameTable; }
152 148 }
153 149
154 150 public override string NamespaceURI {
155 151 get { return m_namespaceUri; }
156 152 }
157 153
158 154 public override XmlNodeType NodeType {
159 155 get {
160 156 switch (m_parser.ElementType) {
161 157 case JSONElementType.BeginObject:
162 158 case JSONElementType.BeginArray:
163 159 return XmlNodeType.Element;
164 160 case JSONElementType.EndObject:
165 161 case JSONElementType.EndArray:
166 162 return XmlNodeType.EndElement;
167 163 case JSONElementType.Value:
168 164 switch (m_valueContext) {
169 165 case ValueContext.ElementStart:
170 166 case ValueContext.ElementEmpty:
171 167 return XmlNodeType.Element;
172 168 case ValueContext.ElementValue:
173 169 return XmlNodeType.Text;
174 170 case ValueContext.ElementEnd:
175 171 return XmlNodeType.EndElement;
176 172 default:
177 173 throw new InvalidOperationException();
178 174 }
179 175 default:
180 176 throw new InvalidOperationException();
181 177 }
182 178 }
183 179 }
184 180
185 181 public override string Prefix {
186 182 get { return m_prefix; }
187 183 }
188 184
189 185 public override bool Read() {
190 186 if (m_state != System.Xml.ReadState.Interactive && m_state != System.Xml.ReadState.Initial)
191 187 return false;
192 188
193 189 if (m_state == ReadState.Initial)
194 190 m_state = System.Xml.ReadState.Interactive;
195 191
196 192 try {
197 193 switch (m_parser.ElementType) {
198 194 case JSONElementType.Value:
199 195 switch (m_valueContext) {
200 196 case ValueContext.ElementStart:
201 197 SetLocalName(String.Empty);
202 198 m_valueContext = ValueContext.ElementValue;
203 199 return true;
204 200 case ValueContext.ElementValue:
205 201 RestoreLocalName();
206 202 m_valueContext = ValueContext.ElementEnd;
207 203 return true;
208 204 case ValueContext.ElementEmpty:
209 205 case ValueContext.ElementEnd:
210 206 RestoreLocalName();
211 207 break;
212 208 }
213 209 break;
214 210 case JSONElementType.EndArray:
215 211 case JSONElementType.EndObject:
216 212 RestoreLocalName();
217 213 break;
218 214 }
219 215 string itemName = m_parser.ElementType == JSONElementType.None ? m_rootName : m_flattenArrays ? m_localName.localName : m_arrayItemName;
220 216 while (m_parser.Read()) {
221 217 if (!String.IsNullOrEmpty(m_parser.ElementName))
222 218 itemName = m_parser.ElementName;
223 219
224 220 switch (m_parser.ElementType) {
225 221 case JSONElementType.BeginArray:
226 222 if (m_flattenArrays && !m_localName.isArray) {
227 223 m_depthCorrection--;
228 224 SetLocalName(itemName, true);
229 225 continue;
230 226 } else {
231 227 SetLocalName(itemName, true);
232 228 }
233 229 break;
234 230 case JSONElementType.BeginObject:
235 231 SetLocalName(itemName);
236 232 break;
237 233 case JSONElementType.EndArray:
238 234 if (m_flattenArrays && !m_localNameStack.Peek().isArray) {
239 235 RestoreLocalName();
240 236 m_depthCorrection++;
241 237 continue;
242 238 }
243 239 break;
244 240 case JSONElementType.EndObject:
245 241 break;
246 242 case JSONElementType.Value:
247 243 SetLocalName(itemName);
248 244 m_valueContext = m_parser.ElementValue == null ? ValueContext.ElementEmpty : ValueContext.ElementStart;
249 245 break;
250 246 default:
251 247 break;
252 248 }
253 249 return true;
254 250 }
255 251
256 252 m_state = System.Xml.ReadState.EndOfFile;
257 253 return false;
258 254 } catch {
259 255 m_state = System.Xml.ReadState.Error;
260 256 throw;
261 257 }
262 258 }
263 259
264 260 public override bool ReadAttributeValue() {
265 261 return false;
266 262 }
267 263
268 264 public override ReadState ReadState {
269 265 get { return m_state; }
270 266 }
271 267
272 268 public override void ResolveEntity() {
273 269 // do nothing
274 270 }
275 271
276 272 public override string Value {
277 273 get {
278 274 if (m_parser.ElementValue == null)
279 275 return String.Empty;
280 276 if (Convert.GetTypeCode(m_parser.ElementValue) == TypeCode.Double)
281 277 return ((double)m_parser.ElementValue).ToString(CultureInfo.InvariantCulture);
282 278 else
283 279 return (string)m_parser.ElementValue;
284 280 }
285 281 }
286 282
287 283 void SetLocalName(string name) {
288 284 m_localNameStack.Push(m_localName);
289 285 m_localName.localName = name;
290 286 m_localName.isArray = false;
291 287 }
292 288
293 289 void SetLocalName(string name, bool isArray) {
294 290 m_localNameStack.Push(m_localName);
295 291 m_localName.localName = name;
296 292 m_localName.isArray = isArray;
297 293 }
298 294
299 295 void RestoreLocalName() {
300 296 m_localName = m_localNameStack.Pop();
301 297 }
302 298
303 299 public override void Close() {
304 300
305 301 }
306 302
307 303 protected override void Dispose(bool disposing) {
308 304 if (disposing) {
309 if (m_disposeParser)
310 305 m_parser.Dispose();
311 306 }
312 307 base.Dispose(disposing);
313 308 }
314 309
310 public static JSONXmlReader Create(string file, JSONXmlReaderOptions options) {
311 return Create(File.OpenText(file), options);
312 }
315 313
316 public static JSONXmlReader OpenFile(string file, JSONXmlReaderOptions options) {
317 var stream = File.OpenText(file);
318 var parser = new JSONParser(stream, true);
319 return new JSONXmlReader(parser, options);
314 public static JSONXmlReader Create(TextReader reader, JSONXmlReaderOptions options) {
315 return new JSONXmlReader(new JSONParser(reader, true), options);
316 }
317
318 public static JSONXmlReader Create(Stream stream, JSONXmlReaderOptions options) {
319 Safe.ArgumentNotNull(stream, "stream");
320 // HACK don't dispose StreaReader to keep stream opened
321 return Create(new StreamReader(stream), options);
320 322 }
321 323 }
322 324 }
@@ -1,69 +1,62
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5 using System.Xml;
6 6
7 7 namespace Implab.JSON {
8 8 /// <summary>
9 9 /// Набор необязательных параметров для <see cref="JSONXmlReader"/>, позволяющий управлять процессом
10 10 /// интерпретации <c>JSON</c> документа.
11 11 /// </summary>
12 12 public class JSONXmlReaderOptions {
13 13 /// <summary>
14 14 /// Пространство имен в котором будут располагаться читаемые элементы документа
15 15 /// </summary>
16 16 public string NamespaceURI {
17 17 get;
18 18 set;
19 19 }
20 20
21 21 /// <summary>
22 22 /// Интерпретировать массивы как множественные элементы (убирает один уровень вложенности)
23 23 /// </summary>
24 24 public bool FlattenArrays {
25 25 get;
26 26 set;
27 27 }
28 28
29 29 /// <summary>
30 30 /// Префикс, для узлов документа
31 31 /// </summary>
32 32 public string NodesPrefix {
33 33 get;
34 34 set;
35 35 }
36 36
37 37 /// <summary>
38 38 /// Имя корневого элемента в xml документе
39 39 /// </summary>
40 40 public string RootName {
41 41 get;
42 42 set;
43 43 }
44 44
45 45 /// <summary>
46 46 /// Имя элемента для массивов, если не включена опция <see cref="FlattenArrays"/>.
47 47 /// </summary>
48 48 public string ArrayItemName {
49 49 get;
50 50 set;
51 51 }
52 52
53 53 /// <summary>
54 54 /// Таблица атомизированных строк для построения документа.
55 55 /// </summary>
56 56 public XmlNameTable NameTable {
57 57 get;
58 58 set;
59 59 }
60 60
61 /// <summary>
62 /// Флаг, означающий, что неужно освободить парсер по окончанию работы.
63 /// </summary>
64 public bool DisposeParser {
65 get;
66 set;
67 61 }
68 62 }
69 }
General Comments 0
You need to be logged in to leave comments. Login now