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