##// END OF EJS Templates
fixed JSON writer
cin -
r115:ffd3702968c7 v2
parent child
Show More
@@ -1,256 +1,258
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.IO;
4 4 using System.Linq;
5 5 using System.Text;
6 6 using System.Threading.Tasks;
7 7
8 8 namespace Implab.JSON {
9 9 public class JSONWriter {
10 10 struct Context {
11 11 public bool needComma;
12 12 public JSONElementContext element;
13 13 }
14 14 Stack<Context> m_contextStack = new Stack<Context>();
15 15 Context m_context;
16 16
17 17 TextWriter m_writer;
18 18 readonly bool m_indent = true;
19 19 readonly int m_indentSize = 4;
20 20
21 21 static readonly char [] _escapeBKS,
22 22 _escapeFWD,
23 23 _escapeCR,
24 24 _escapeNL,
25 25 _escapeTAB,
26 26 _escapeSLASH,
27 27 _escapeBSLASH,
28 28 _escapeQ;
29 29
30 30 static JSONWriter() {
31 31 _escapeBKS = "\\b".ToCharArray();
32 32 _escapeFWD = "\\f".ToCharArray();
33 33 _escapeCR = "\\r".ToCharArray();
34 34 _escapeNL = "\\n".ToCharArray();
35 35 _escapeTAB = "\\t".ToCharArray();
36 36 _escapeBSLASH = "\\\\".ToCharArray();
37 37 _escapeSLASH = "\\/".ToCharArray();
38 38 _escapeQ = "\\\"".ToCharArray();
39 39 }
40 40
41 41 public JSONWriter(TextWriter writer) {
42 42 Safe.ArgumentNotNull(writer, "writer");
43 43
44 44 m_writer = writer;
45 45 }
46 46
47 47 public JSONWriter(TextWriter writer, bool indent) {
48 48 Safe.ArgumentNotNull(writer, "writer");
49 49
50 50 m_writer = writer;
51 51 m_indent = indent;
52 52 }
53 53
54 54 void WriteIndent() {
55 55 if (m_indent) {
56 56 var indent = new char[m_contextStack.Count * m_indentSize + 1];
57 57 indent[0] = '\n';
58 58 for (int i = 1; i < indent.Length; i++)
59 59 indent[i] = ' ';
60 60 m_writer.Write(new String(indent));
61 61 } else {
62 62 m_writer.Write(' ');
63 63 }
64 64 }
65 65
66 66 void WriteMemberName(string name) {
67 67 Safe.ArgumentNotEmpty(name, "name");
68 68 if (m_context.element != JSONElementContext.Object)
69 69 OperationNotApplicable("WriteMember");
70 70 if (m_context.needComma)
71 71 m_writer.Write(",");
72 72
73 73 WriteIndent();
74 74 m_context.needComma = true;
75 75 Write(name);
76 76 m_writer.Write(" : ");
77 77 }
78 78
79 79 public void WriteValue(string name, string value) {
80 80 WriteMemberName(name);
81 81 Write(value);
82 82 }
83 83
84 84 public void WriteValue(string name, bool value) {
85 85 WriteMemberName(name);
86 86 Write(value);
87 87 }
88 88
89 89 public void WriteValue(string name, double value) {
90 90 WriteMemberName(name);
91 91 Write(value);
92 92 }
93 93
94 94 public void WriteValue(string value) {
95 95 if (m_context.element != JSONElementContext.Array)
96 96 OperationNotApplicable("WriteValue");
97 97 if (m_context.needComma)
98 98 m_writer.Write(",");
99 99 WriteIndent();
100 100 m_context.needComma = true;
101 101
102 102 Write(value);
103 103 }
104 104
105 105 public void WriteValue(bool value) {
106 106 if (m_context.element != JSONElementContext.Array)
107 107 OperationNotApplicable("WriteValue");
108 108 if (m_context.needComma)
109 109 m_writer.Write(",");
110 110 m_context.needComma = true;
111 111
112 112 WriteIndent();
113 113 Write(value);
114 114 }
115 115
116 116 public void WriteValue(double value) {
117 117 if (m_context.element != JSONElementContext.Array)
118 118 OperationNotApplicable("WriteValue");
119 119 if (m_context.needComma)
120 120 m_writer.Write(",");
121 121 m_context.needComma = true;
122 122
123 123 WriteIndent();
124 124 Write(value);
125 125 }
126 126
127 127 public void BeginObject() {
128 128 if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array)
129 129 OperationNotApplicable("BeginObject");
130 130 if (m_context.needComma)
131 131 m_writer.Write(",");
132 132
133 133 WriteIndent();
134 134
135 135 m_context.needComma = true;
136 136
137 137 m_contextStack.Push(m_context);
138 138
139 139 m_context = new Context { element = JSONElementContext.Object, needComma = false };
140 140 m_writer.Write("{");
141 141 }
142 142
143 143 public void BeginObject(string name) {
144 144 WriteMemberName(name);
145 145
146 146 m_contextStack.Push(m_context);
147 147
148 148 m_context = new Context { element = JSONElementContext.Object, needComma = false };
149 149 m_writer.Write("{");
150 150 }
151 151
152 152 public void EndObject() {
153 153 if (m_context.element != JSONElementContext.Object)
154 154 OperationNotApplicable("EndArray");
155 155
156 156 m_context = m_contextStack.Pop();
157 157 WriteIndent();
158 158 m_writer.Write("}");
159 159 }
160 160
161 161 public void BeginArray() {
162 162 if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array)
163 163 throw new InvalidOperationException();
164 164 if (m_context.needComma) {
165 165 m_writer.Write(",");
166 166
167 167 }
168 168 m_context.needComma = true;
169 169
170 170 WriteIndent();
171 171 m_contextStack.Push(m_context);
172 172 m_context = new Context { element = JSONElementContext.Array, needComma = false };
173 173 m_writer.Write("[");
174 174 }
175 175
176 176 public void BeginArray(string name) {
177 177 WriteMemberName(name);
178 178
179 179 m_contextStack.Push(m_context);
180 180
181 181 m_context = new Context { element = JSONElementContext.Array, needComma = false };
182 182 m_writer.Write("[");
183 183 }
184 184
185 185 public void EndArray() {
186 186 if (m_context.element != JSONElementContext.Array)
187 187 OperationNotApplicable("EndArray");
188 188
189 189 m_context = m_contextStack.Pop();
190 190 WriteIndent();
191 191 m_writer.Write("]");
192 192 }
193 193
194 194 void Write(bool value) {
195 195 m_writer.Write(value ? "true" : "false");
196 196 }
197 197
198 198
199 199 void Write(string value) {
200 if (value == null)
200 if (value == null) {
201 201 m_writer.Write("null");
202 return;
203 }
202 204
203 205 var chars = value.ToCharArray();
204 206 m_writer.Write('"');
205 207
206 208 for (int i = 0; i < chars.Length; i++) {
207 209 var ch = chars[i];
208 210
209 211 switch (ch) {
210 212 case '\b':
211 213 m_writer.Write(_escapeBKS);
212 214 break;
213 215 case '\f':
214 216 m_writer.Write(_escapeFWD);
215 217 break;
216 218 case '\r':
217 219 m_writer.Write(_escapeCR);
218 220 break;
219 221 case '\n':
220 222 m_writer.Write(_escapeNL);
221 223 break;
222 224 case '\t':
223 225 m_writer.Write(_escapeTAB);
224 226 break;
225 227 case '\\':
226 228 m_writer.Write(_escapeBSLASH);
227 229 break;
228 230 case '/':
229 231 m_writer.Write(_escapeSLASH);
230 232 break;
231 233 case '"':
232 234 m_writer.Write(_escapeQ);
233 235 break;
234 236 default:
235 237 if (ch < 0x20) {
236 238 m_writer.Write("\\u00{0:x2}",(int)ch);
237 239 } else {
238 240 m_writer.Write(ch);
239 241 }
240 242 break;
241 243 }
242 244 }
243 245
244 246 m_writer.Write('"');
245 247 }
246 248
247 249 void Write(double value) {
248 250 m_writer.Write(value);
249 251 }
250 252
251 253 void OperationNotApplicable(string opName) {
252 254 throw new InvalidOperationException(String.Format("The operation '{0}' isn't applicable in the context of '{1}'", opName, m_context.element ));
253 255 }
254 256
255 257 }
256 258 }
General Comments 0
You need to be logged in to leave comments. Login now