blob: 07dee63e3b485f3c5c8f3c8de8ad2171b794844d [file] [log] [blame]
Mark Slee844ac122007-11-27 08:38:52 +00001// Copyright (c) 2006- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
7package com.facebook.thrift.protocol;
8
9import com.facebook.thrift.TException;
10import com.facebook.thrift.transport.TTransport;
11import java.io.UnsupportedEncodingException;
12import java.util.Stack;
13
14/**
15 * JSON protocol implementation for thrift.
16 *
17 * @author Joydeep Sen Sarma <jssarma@facebook.com>
18 * @author Mark Slee <mcslee@facebook.com>
19 */
20public class TJSONProtocol extends TProtocol {
21
22 /**
23 * Factory
24 */
25 public static class Factory implements TProtocolFactory {
26 public TProtocol getProtocol(TTransport trans) {
27 return new TJSONProtocol(trans);
28 }
29 }
30
31 public static final byte[] COMMA = new byte[] {','};
32 public static final byte[] COLON = new byte[] {':'};
33 public static final byte[] QUOTE = new byte[] {'"'};
34 public static final byte[] LBRACE = new byte[] {'{'};
35 public static final byte[] RBRACE = new byte[] {'}'};
36 public static final byte[] LBRACKET = new byte[] {'['};
37 public static final byte[] RBRACKET = new byte[] {']'};
38
39 protected class Context {
40 protected void write() throws TException {}
41 }
42
43 protected class ListContext extends Context {
44 protected boolean first_ = true;
45
46 protected void write() throws TException {
47 if (first_) {
48 first_ = false;
49 } else {
50 trans_.write(COMMA);
51 }
52 }
53 }
54
55 protected class StructContext extends Context {
56 protected boolean first_ = true;
57 protected boolean colon_ = true;
58
59 protected void write() throws TException {
60 if (first_) {
61 first_ = false;
62 colon_ = true;
63 } else {
64 trans_.write(colon_ ? COLON : COMMA);
65 colon_ = !colon_;
66 }
67 }
68 }
69
70 protected final Context BASE_CONTEXT = new Context();
71
72 /**
73 * Stack of nested contexts that we may be in.
74 */
75 protected Stack<Context> writeContextStack_ = new Stack<Context>();
76
77 /**
78 * Current context that we are in
79 */
80 protected Context writeContext_ = BASE_CONTEXT;
81
82 /**
83 * Push a new write context onto the stack.
84 */
85 protected void pushWriteContext(Context c) {
86 writeContextStack_.push(writeContext_);
87 writeContext_ = c;
88 }
89
90 /**
91 * Pop the last write context off the stack
92 */
93 protected void popWriteContext() {
94 writeContext_ = writeContextStack_.pop();
95 }
96
97 /**
98 * Constructor
99 */
100 public TJSONProtocol(TTransport trans) {
101 super(trans);
102 }
103
104 public void writeMessageBegin(TMessage message) throws TException {
105 trans_.write(LBRACKET);
106 pushWriteContext(new ListContext());
107 writeString(message.name);
108 writeByte(message.type);
109 writeI32(message.seqid);
110 }
111
112 public void writeMessageEnd() throws TException {
113 popWriteContext();
114 trans_.write(RBRACKET);
115 }
116
117 public void writeStructBegin(TStruct struct) throws TException {
118 writeContext_.write();
119 trans_.write(LBRACE);
120 pushWriteContext(new StructContext());
121 }
122
123 public void writeStructEnd() throws TException {
124 popWriteContext();
125 trans_.write(RBRACE);
126 }
127
128 public void writeFieldBegin(TField field) throws TException {
129 // Note that extra type information is omitted in JSON!
130 writeString(field.name);
131 }
132
133 public void writeFieldEnd() {}
134
135 public void writeFieldStop() {}
136
137 public void writeMapBegin(TMap map) throws TException {
138 writeContext_.write();
139 trans_.write(LBRACE);
140 pushWriteContext(new StructContext());
141 // No metadata!
142 }
143
144 public void writeMapEnd() throws TException {
145 popWriteContext();
146 trans_.write(RBRACE);
147 }
148
149 public void writeListBegin(TList list) throws TException {
150 writeContext_.write();
151 trans_.write(LBRACKET);
152 pushWriteContext(new ListContext());
153 // No metadata!
154 }
155
156 public void writeListEnd() throws TException {
157 popWriteContext();
158 trans_.write(RBRACKET);
159 }
160
161 public void writeSetBegin(TSet set) throws TException {
162 writeContext_.write();
163 trans_.write(LBRACKET);
164 pushWriteContext(new ListContext());
165 // No metadata!
166 }
167
168 public void writeSetEnd() throws TException {
169 popWriteContext();
170 trans_.write(RBRACKET);
171 }
172
173 public void writeBool(boolean b) throws TException {
174 writeByte(b ? (byte)1 : (byte)0);
175 }
176
177 public void writeByte(byte b) throws TException {
178 writeI32(b);
179 }
180
181 public void writeI16(short i16) throws TException {
182 writeI32(i16);
183 }
184
185 public void writeI32(int i32) throws TException {
186 writeContext_.write();
187 _writeStringData(Integer.toString(i32));
188 }
189
190 public void _writeStringData(String s) throws TException {
191 try {
192 byte[] b = s.getBytes("UTF-8");
193 trans_.write(b);
194 } catch (UnsupportedEncodingException uex) {
195 throw new TException("JVM DOES NOT SUPPORT UTF-8");
196 }
197 }
198
199 public void writeI64(long i64) throws TException {
200 writeContext_.write();
201 _writeStringData(Long.toString(i64));
202 }
203
204 public void writeDouble(double dub) throws TException {
205 writeContext_.write();
206 _writeStringData(Double.toString(dub));
207 }
208
209 public void writeString(String str) throws TException {
210 writeContext_.write();
211 trans_.write(QUOTE);
212
213 int length = str.length();
214 StringBuffer escape = new StringBuffer(length);
215 char c;
216 for (int i = 0; i < length; ++i) {
217 c = str.charAt(i);
218 switch (c) {
219 case '"':
220 case '\\':
221 escape.append('\\');
222 escape.append(c);
223 break;
224 default:
225 escape.append(c);
226 break;
227 }
228 }
229 _writeStringData(escape.toString());
230 trans_.write(QUOTE);
231 }
232
233 public void writeBinary(byte[] bin) throws TException {
234 try {
235 // TODO(mcslee): Fix this
236 writeString(new String(bin, "UTF-8"));
237 } catch (UnsupportedEncodingException uex) {
238 throw new TException("JVM DOES NOT SUPPORT UTF-8");
239 }
240 }
241
242 /**
243 * Reading methods.
244 */
245
246 public TMessage readMessageBegin() throws TException {
247 TMessage message = new TMessage();
248 // TODO(mcslee): implement
249 return message;
250 }
251
252 public void readMessageEnd() {}
253
254 public TStruct readStructBegin() {
255 // TODO(mcslee): implement
256 return new TStruct();
257 }
258
259 public void readStructEnd() {}
260
261 public TField readFieldBegin() throws TException {
262 TField field = new TField();
263 // TODO(mcslee): implement
264 return field;
265 }
266
267 public void readFieldEnd() {}
268
269 public TMap readMapBegin() throws TException {
270 TMap map = new TMap();
271 // TODO(mcslee): implement
272 return map;
273 }
274
275 public void readMapEnd() {}
276
277 public TList readListBegin() throws TException {
278 TList list = new TList();
279 // TODO(mcslee): implement
280 return list;
281 }
282
283 public void readListEnd() {}
284
285 public TSet readSetBegin() throws TException {
286 TSet set = new TSet();
287 // TODO(mcslee): implement
288 return set;
289 }
290
291 public void readSetEnd() {}
292
293 public boolean readBool() throws TException {
294 return (readByte() == 1);
295 }
296
297 public byte readByte() throws TException {
298 // TODO(mcslee): implement
299 return 0;
300 }
301
302 public short readI16() throws TException {
303 // TODO(mcslee): implement
304 return 0;
305 }
306
307 public int readI32() throws TException {
308 // TODO(mcslee): implement
309 return 0;
310 }
311
312 public long readI64() throws TException {
313 // TODO(mcslee): implement
314 return 0;
315 }
316
317 public double readDouble() throws TException {
318 // TODO(mcslee): implement
319 return 0;
320 }
321
322 public String readString() throws TException {
323 // TODO(mcslee): implement
324 return "";
325 }
326
327 public String readStringBody(int size) throws TException {
328 // TODO(mcslee): implement
329 return "";
330 }
331
332 public byte[] readBinary() throws TException {
333 // TODO(mcslee): implement
334 return new byte[0];
335 }
336
337}