Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: sdk/lib/convert/json.dart

Issue 1964953003: Make dart:convert strong mode clean. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Remove unnecessary dynamics. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sdk/lib/convert/html_escape.dart ('k') | sdk/lib/convert/line_splitter.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart.convert; 5 part of dart.convert;
6 6
7 /** 7 /**
8 * Error thrown by JSON serialization if an object cannot be serialized. 8 * Error thrown by JSON serialization if an object cannot be serialized.
9 * 9 *
10 * The [unsupportedObject] field holds that object that failed to be serialized. 10 * The [unsupportedObject] field holds that object that failed to be serialized.
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 * Converts [value] to a JSON string. 132 * Converts [value] to a JSON string.
133 * 133 *
134 * If value contains objects that are not directly encodable to a JSON 134 * If value contains objects that are not directly encodable to a JSON
135 * string (a value that is not a number, boolean, string, null, list or a map 135 * string (a value that is not a number, boolean, string, null, list or a map
136 * with string keys), the [toEncodable] function is used to convert it to an 136 * with string keys), the [toEncodable] function is used to convert it to an
137 * object that must be directly encodable. 137 * object that must be directly encodable.
138 * 138 *
139 * If [toEncodable] is omitted, it defaults to a function that returns the 139 * If [toEncodable] is omitted, it defaults to a function that returns the
140 * result of calling `.toJson()` on the unencodable object. 140 * result of calling `.toJson()` on the unencodable object.
141 */ 141 */
142 String encode(Object value, {toEncodable(var object)}) { 142 String encode(Object value, {toEncodable(object)}) {
143 if (toEncodable == null) toEncodable = _toEncodable; 143 if (toEncodable == null) toEncodable = _toEncodable;
144 if (toEncodable == null) return encoder.convert(value); 144 if (toEncodable == null) return encoder.convert(value);
145 return new JsonEncoder(toEncodable).convert(value); 145 return new JsonEncoder(toEncodable).convert(value);
146 } 146 }
147 147
148 JsonEncoder get encoder { 148 JsonEncoder get encoder {
149 if (_toEncodable == null) return const JsonEncoder(); 149 if (_toEncodable == null) return const JsonEncoder();
150 return new JsonEncoder(_toEncodable); 150 return new JsonEncoder(_toEncodable);
151 } 151 }
152 152
153 JsonDecoder get decoder { 153 JsonDecoder get decoder {
154 if (_reviver == null) return const JsonDecoder(); 154 if (_reviver == null) return const JsonDecoder();
155 return new JsonDecoder(_reviver); 155 return new JsonDecoder(_reviver);
156 } 156 }
157 } 157 }
158 158
159 /** 159 /**
160 * This class converts JSON objects to strings. 160 * This class converts JSON objects to strings.
161 */ 161 */
162 class JsonEncoder extends ChunkedConverter<Object, String, Object, String> { 162 class JsonEncoder extends Converter<Object, String> {
163 /** 163 /**
164 * The string used for indention. 164 * The string used for indention.
165 * 165 *
166 * When generating multi-line output, this string is inserted once at the 166 * When generating multi-line output, this string is inserted once at the
167 * beginning of each indented line for each level of indentation. 167 * beginning of each indented line for each level of indentation.
168 * 168 *
169 * If `null`, the output is encoded as a single line. 169 * If `null`, the output is encoded as a single line.
170 */ 170 */
171 final String indent; 171 final String indent;
172 172
173 /** 173 /**
174 * Function called on non-encodable objects to return a replacement 174 * Function called on non-encodable objects to return a replacement
175 * encodable object that will be encoded in the orignal's place. 175 * encodable object that will be encoded in the orignal's place.
176 */ 176 */
177 final Function _toEncodable; 177 final _ToEncodable _toEncodable;
178 178
179 /** 179 /**
180 * Creates a JSON encoder. 180 * Creates a JSON encoder.
181 * 181 *
182 * The JSON encoder handles numbers, strings, booleans, null, lists and 182 * The JSON encoder handles numbers, strings, booleans, null, lists and
183 * maps directly. 183 * maps directly.
184 * 184 *
185 * Any other object is attempted converted by [toEncodable] to an 185 * Any other object is attempted converted by [toEncodable] to an
186 * object that is of one of the convertible types. 186 * object that is of one of the convertible types.
187 * 187 *
188 * If [toEncodable] is omitted, it defaults to calling `.toJson()` on 188 * If [toEncodable] is omitted, it defaults to calling `.toJson()` on
189 * the object. 189 * the object.
190 */ 190 */
191 const JsonEncoder([Object toEncodable(Object nonSerializable)]) 191 const JsonEncoder([toEncodable(nonSerializable)])
192 : this.indent = null, 192 : this.indent = null,
193 this._toEncodable = toEncodable; 193 this._toEncodable = toEncodable;
194 194
195 /** 195 /**
196 * Creates a JSON encoder that creates multi-line JSON. 196 * Creates a JSON encoder that creates multi-line JSON.
197 * 197 *
198 * The encoding of elements of lists and maps are indented and put on separate 198 * The encoding of elements of lists and maps are indented and put on separate
199 * lines. The [indent] string is prepended to these elements, once for each 199 * lines. The [indent] string is prepended to these elements, once for each
200 * level of indentation. 200 * level of indentation.
201 * 201 *
202 * If [indent] is `null`, the output is encoded as a single line. 202 * If [indent] is `null`, the output is encoded as a single line.
203 * 203 *
204 * The JSON encoder handles numbers, strings, booleans, null, lists and 204 * The JSON encoder handles numbers, strings, booleans, null, lists and
205 * maps directly. 205 * maps directly.
206 * 206 *
207 * Any other object is attempted converted by [toEncodable] to an 207 * Any other object is attempted converted by [toEncodable] to an
208 * object that is of one of the convertible types. 208 * object that is of one of the convertible types.
209 * 209 *
210 * If [toEncodable] is omitted, it defaults to calling `.toJson()` on 210 * If [toEncodable] is omitted, it defaults to calling `.toJson()` on
211 * the object. 211 * the object.
212 */ 212 */
213 const JsonEncoder.withIndent(this.indent, 213 const JsonEncoder.withIndent(this.indent, [toEncodable(nonSerializable)])
214 [Object toEncodable(Object nonSerializable)])
215 : this._toEncodable = toEncodable; 214 : this._toEncodable = toEncodable;
216 215
217 /** 216 /**
218 * Converts [object] to a JSON [String]. 217 * Converts [object] to a JSON [String].
219 * 218 *
220 * Directly serializable values are [num], [String], [bool], and [Null], as 219 * Directly serializable values are [num], [String], [bool], and [Null], as
221 * well as some [List] and [Map] values. For [List], the elements must all be 220 * well as some [List] and [Map] values. For [List], the elements must all be
222 * serializable. For [Map], the keys must be [String] and the values must be 221 * serializable. For [Map], the keys must be [String] and the values must be
223 * serializable. 222 * serializable.
224 * 223 *
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 return new _JsonUtf8EncoderSink(sink._sink, _toEncodable, 260 return new _JsonUtf8EncoderSink(sink._sink, _toEncodable,
262 JsonUtf8Encoder._utf8Encode(indent), 261 JsonUtf8Encoder._utf8Encode(indent),
263 JsonUtf8Encoder.DEFAULT_BUFFER_SIZE); 262 JsonUtf8Encoder.DEFAULT_BUFFER_SIZE);
264 } 263 }
265 return new _JsonEncoderSink(sink, _toEncodable, indent); 264 return new _JsonEncoderSink(sink, _toEncodable, indent);
266 } 265 }
267 266
268 // Override the base class's bind, to provide a better type. 267 // Override the base class's bind, to provide a better type.
269 Stream<String> bind(Stream<Object> stream) => super.bind(stream); 268 Stream<String> bind(Stream<Object> stream) => super.bind(stream);
270 269
271 Converter<Object, dynamic> fuse(Converter<String, dynamic> other) { 270 Converter<Object, dynamic/*=T*/> fuse/*<T>*/(
271 Converter<String, dynamic/*=T*/> other) {
272 if (other is Utf8Encoder) { 272 if (other is Utf8Encoder) {
273 return new JsonUtf8Encoder(indent, _toEncodable); 273 return new JsonUtf8Encoder(indent, _toEncodable)
274 as dynamic/*=Converter<Object, T>*/;
274 } 275 }
275 return super.fuse(other); 276 return super.fuse/*<T>*/(other);
276 } 277 }
277 } 278 }
278 279
279 /** 280 /**
280 * Encoder that encodes a single object as a UTF-8 encoded JSON string. 281 * Encoder that encodes a single object as a UTF-8 encoded JSON string.
281 * 282 *
282 * This encoder works equivalently to first converting the object to 283 * This encoder works equivalently to first converting the object to
283 * a JSON string, and then UTF-8 encoding the string, but without 284 * a JSON string, and then UTF-8 encoding the string, but without
284 * creating an intermediate string. 285 * creating an intermediate string.
285 */ 286 */
286 class JsonUtf8Encoder extends 287 class JsonUtf8Encoder extends Converter<Object, List<int>> {
287 ChunkedConverter<Object, List<int>, Object, List<int>> {
288 /** Default buffer size used by the JSON-to-UTF-8 encoder. */ 288 /** Default buffer size used by the JSON-to-UTF-8 encoder. */
289 static const int DEFAULT_BUFFER_SIZE = 256; 289 static const int DEFAULT_BUFFER_SIZE = 256;
290 /** Indentation used in pretty-print mode, `null` if not pretty. */ 290 /** Indentation used in pretty-print mode, `null` if not pretty. */
291 final List<int> _indent; 291 final List<int> _indent;
292 /** Function called with each un-encodable object encountered. */ 292 /** Function called with each un-encodable object encountered. */
293 final Function _toEncodable; 293 final _ToEncodable _toEncodable;
294 /** UTF-8 buffer size. */ 294 /** UTF-8 buffer size. */
295 final int _bufferSize; 295 final int _bufferSize;
296 296
297 /** 297 /**
298 * Create converter. 298 * Create converter.
299 * 299 *
300 * If [indent] is non-`null`, the converter attempts to "pretty-print" the 300 * If [indent] is non-`null`, the converter attempts to "pretty-print" the
301 * JSON, and uses `indent` as the indentation. Otherwise the result has no 301 * JSON, and uses `indent` as the indentation. Otherwise the result has no
302 * whitespace outside of string literals. 302 * whitespace outside of string literals.
303 * If `indent` contains characters that are not valid JSON whitespace 303 * If `indent` contains characters that are not valid JSON whitespace
304 * characters, the result will not be valid JSON. JSON whitespace characters 304 * characters, the result will not be valid JSON. JSON whitespace characters
305 * are space (U+0020), tab (U+0009), line feed (U+000a) and carriage return 305 * are space (U+0020), tab (U+0009), line feed (U+000a) and carriage return
306 * (U+000d) ([ECMA 306 * (U+000d) ([ECMA
307 * 404](http://www.ecma-international.org/publications/standards/Ecma-404.htm) ). 307 * 404](http://www.ecma-international.org/publications/standards/Ecma-404.htm) ).
308 * 308 *
309 * The [bufferSize] is the size of the internal buffers used to collect 309 * The [bufferSize] is the size of the internal buffers used to collect
310 * UTF-8 code units. 310 * UTF-8 code units.
311 * If using [startChunkedConversion], it will be the size of the chunks. 311 * If using [startChunkedConversion], it will be the size of the chunks.
312 * 312 *
313 * The JSON encoder handles numbers, strings, booleans, null, lists and maps 313 * The JSON encoder handles numbers, strings, booleans, null, lists and maps
314 * directly. 314 * directly.
315 * 315 *
316 * Any other object is attempted converted by [toEncodable] to an object that 316 * Any other object is attempted converted by [toEncodable] to an object that
317 * is of one of the convertible types. 317 * is of one of the convertible types.
318 * 318 *
319 * If [toEncodable] is omitted, it defaults to calling `.toJson()` on the 319 * If [toEncodable] is omitted, it defaults to calling `.toJson()` on the
320 * object. 320 * object.
321 */ 321 */
322 JsonUtf8Encoder([String indent, 322 JsonUtf8Encoder([String indent,
323 toEncodable(Object object), 323 toEncodable(object),
324 int bufferSize = DEFAULT_BUFFER_SIZE]) 324 int bufferSize = DEFAULT_BUFFER_SIZE])
325 : _indent = _utf8Encode(indent), 325 : _indent = _utf8Encode(indent),
326 _toEncodable = toEncodable, 326 _toEncodable = toEncodable,
327 _bufferSize = bufferSize; 327 _bufferSize = bufferSize;
328 328
329 static List<int> _utf8Encode(String string) { 329 static List<int> _utf8Encode(String string) {
330 if (string == null) return null; 330 if (string == null) return null;
331 if (string.isEmpty) return new Uint8List(0); 331 if (string.isEmpty) return new Uint8List(0);
332 checkAscii: { 332 checkAscii: {
333 for (int i = 0; i < string.length; i++) { 333 for (int i = 0; i < string.length; i++) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 byteSink = new ByteConversionSink.from(sink); 388 byteSink = new ByteConversionSink.from(sink);
389 } 389 }
390 return new _JsonUtf8EncoderSink(byteSink, _toEncodable, 390 return new _JsonUtf8EncoderSink(byteSink, _toEncodable,
391 _indent, _bufferSize); 391 _indent, _bufferSize);
392 } 392 }
393 393
394 // Override the base class's bind, to provide a better type. 394 // Override the base class's bind, to provide a better type.
395 Stream<List<int>> bind(Stream<Object> stream) { 395 Stream<List<int>> bind(Stream<Object> stream) {
396 return super.bind(stream); 396 return super.bind(stream);
397 } 397 }
398
399 Converter<Object, dynamic> fuse(Converter<List<int>, dynamic> other) {
400 return super.fuse(other);
401 }
402 } 398 }
403 399
404 /** 400 /**
405 * Implements the chunked conversion from object to its JSON representation. 401 * Implements the chunked conversion from object to its JSON representation.
406 * 402 *
407 * The sink only accepts one value, but will produce output in a chunked way. 403 * The sink only accepts one value, but will produce output in a chunked way.
408 */ 404 */
409 class _JsonEncoderSink extends ChunkedConversionSink<Object> { 405 class _JsonEncoderSink extends ChunkedConversionSink<Object> {
410 final String _indent; 406 final String _indent;
411 final Function _toEncodable; 407 final _ToEncodable _toEncodable;
412 final StringConversionSink _sink; 408 final StringConversionSink _sink;
413 bool _isDone = false; 409 bool _isDone = false;
414 410
415 _JsonEncoderSink(this._sink, this._toEncodable, this._indent); 411 _JsonEncoderSink(this._sink, this._toEncodable, this._indent);
416 412
417 /** 413 /**
418 * Encodes the given object [o]. 414 * Encodes the given object [o].
419 * 415 *
420 * It is an error to invoke this method more than once on any instance. While 416 * It is an error to invoke this method more than once on any instance. While
421 * this makes the input effectly non-chunked the output will be generated in 417 * this makes the input effectly non-chunked the output will be generated in
(...skipping 12 matching lines...) Expand all
434 void close() { /* do nothing */ } 430 void close() { /* do nothing */ }
435 } 431 }
436 432
437 /** 433 /**
438 * Sink returned when starting a chunked conversion from object to bytes. 434 * Sink returned when starting a chunked conversion from object to bytes.
439 */ 435 */
440 class _JsonUtf8EncoderSink extends ChunkedConversionSink<Object> { 436 class _JsonUtf8EncoderSink extends ChunkedConversionSink<Object> {
441 /** The byte sink receiveing the encoded chunks. */ 437 /** The byte sink receiveing the encoded chunks. */
442 final ByteConversionSink _sink; 438 final ByteConversionSink _sink;
443 final List<int> _indent; 439 final List<int> _indent;
444 final Function _toEncodable; 440 final _ToEncodable _toEncodable;
445 final int _bufferSize; 441 final int _bufferSize;
446 bool _isDone = false; 442 bool _isDone = false;
447 _JsonUtf8EncoderSink(this._sink, this._toEncodable, this._indent, 443 _JsonUtf8EncoderSink(this._sink, this._toEncodable, this._indent,
448 this._bufferSize); 444 this._bufferSize);
449 445
450 /** Callback called for each slice of result bytes. */ 446 /** Callback called for each slice of result bytes. */
451 void _addChunk(Uint8List chunk, int start, int end) { 447 void _addChunk(Uint8List chunk, int start, int end) {
452 _sink.addSlice(chunk, start, end, false); 448 _sink.addSlice(chunk, start, end, false);
453 } 449 }
454 450
(...skipping 12 matching lines...) Expand all
467 if (!_isDone) { 463 if (!_isDone) {
468 _isDone = true; 464 _isDone = true;
469 _sink.close(); 465 _sink.close();
470 } 466 }
471 } 467 }
472 } 468 }
473 469
474 /** 470 /**
475 * This class parses JSON strings and builds the corresponding objects. 471 * This class parses JSON strings and builds the corresponding objects.
476 */ 472 */
477 class JsonDecoder extends ChunkedConverter<String, Object, String, Object> { 473 class JsonDecoder extends Converter<String, Object> {
478 final _Reviver _reviver; 474 final _Reviver _reviver;
479 /** 475 /**
480 * Constructs a new JsonDecoder. 476 * Constructs a new JsonDecoder.
481 * 477 *
482 * The [reviver] may be `null`. 478 * The [reviver] may be `null`.
483 */ 479 */
484 const JsonDecoder([reviver(var key, var value)]) : this._reviver = reviver; 480 const JsonDecoder([reviver(var key, var value)]) : this._reviver = reviver;
485 481
486 /** 482 /**
487 * Converts the given JSON-string [input] to its corresponding object. 483 * Converts the given JSON-string [input] to its corresponding object.
(...skipping 22 matching lines...) Expand all
510 // Override the base class's bind, to provide a better type. 506 // Override the base class's bind, to provide a better type.
511 Stream<Object> bind(Stream<String> stream) => super.bind(stream); 507 Stream<Object> bind(Stream<String> stream) => super.bind(stream);
512 } 508 }
513 509
514 // Internal optimized JSON parsing implementation. 510 // Internal optimized JSON parsing implementation.
515 external _parseJson(String source, reviver(key, value)); 511 external _parseJson(String source, reviver(key, value));
516 512
517 513
518 // Implementation of encoder/stringifier. 514 // Implementation of encoder/stringifier.
519 515
520 Object _defaultToEncodable(object) => object.toJson(); 516 dynamic _defaultToEncodable(dynamic object) => object.toJson();
521 517
522 /** 518 /**
523 * JSON encoder that traverses an object structure and writes JSON source. 519 * JSON encoder that traverses an object structure and writes JSON source.
524 * 520 *
525 * This is an abstract implementation that doesn't decide on the output 521 * This is an abstract implementation that doesn't decide on the output
526 * format, but writes the JSON through abstract methods like [writeString]. 522 * format, but writes the JSON through abstract methods like [writeString].
527 */ 523 */
528 abstract class _JsonStringifier { 524 abstract class _JsonStringifier {
529 // Character code constants. 525 // Character code constants.
530 static const int BACKSPACE = 0x08; 526 static const int BACKSPACE = 0x08;
531 static const int TAB = 0x09; 527 static const int TAB = 0x09;
532 static const int NEWLINE = 0x0a; 528 static const int NEWLINE = 0x0a;
533 static const int CARRIAGE_RETURN = 0x0d; 529 static const int CARRIAGE_RETURN = 0x0d;
534 static const int FORM_FEED = 0x0c; 530 static const int FORM_FEED = 0x0c;
535 static const int QUOTE = 0x22; 531 static const int QUOTE = 0x22;
536 static const int CHAR_0 = 0x30; 532 static const int CHAR_0 = 0x30;
537 static const int BACKSLASH = 0x5c; 533 static const int BACKSLASH = 0x5c;
538 static const int CHAR_b = 0x62; 534 static const int CHAR_b = 0x62;
539 static const int CHAR_f = 0x66; 535 static const int CHAR_f = 0x66;
540 static const int CHAR_n = 0x6e; 536 static const int CHAR_n = 0x6e;
541 static const int CHAR_r = 0x72; 537 static const int CHAR_r = 0x72;
542 static const int CHAR_t = 0x74; 538 static const int CHAR_t = 0x74;
543 static const int CHAR_u = 0x75; 539 static const int CHAR_u = 0x75;
544 540
545 /** List of objects currently being traversed. Used to detect cycles. */ 541 /** List of objects currently being traversed. Used to detect cycles. */
546 final List _seen = new List(); 542 final List _seen = new List();
547 /** Function called for each un-encodable object encountered. */ 543 /** Function called for each un-encodable object encountered. */
548 final Function _toEncodable; 544 final _ToEncodable _toEncodable;
549 545
550 _JsonStringifier(Object _toEncodable(Object o)) 546 _JsonStringifier(toEncodable(o))
551 : _toEncodable = (_toEncodable != null) ? _toEncodable 547 : _toEncodable = toEncodable ?? _defaultToEncodable;
552 : _defaultToEncodable;
553 548
554 /** Append a string to the JSON output. */ 549 /** Append a string to the JSON output. */
555 void writeString(String characters); 550 void writeString(String characters);
556 /** Append part of a string to the JSON output. */ 551 /** Append part of a string to the JSON output. */
557 void writeStringSlice(String characters, int start, int end); 552 void writeStringSlice(String characters, int start, int end);
558 /** Append a single character, given by its code point, to the JSON output. */ 553 /** Append a single character, given by its code point, to the JSON output. */
559 void writeCharCode(int charCode); 554 void writeCharCode(int charCode);
560 /** Write a number to the JSON output. */ 555 /** Write a number to the JSON output. */
561 void writeNumber(num number); 556 void writeNumber(num number);
562 557
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 writeObject(list[0]); 707 writeObject(list[0]);
713 for (int i = 1; i < list.length; i++) { 708 for (int i = 1; i < list.length; i++) {
714 writeString(','); 709 writeString(',');
715 writeObject(list[i]); 710 writeObject(list[i]);
716 } 711 }
717 } 712 }
718 writeString(']'); 713 writeString(']');
719 } 714 }
720 715
721 /** Serialize a [Map]. */ 716 /** Serialize a [Map]. */
722 bool writeMap(Map<String, Object> map) { 717 bool writeMap(Map map) {
723 if (map.isEmpty) { 718 if (map.isEmpty) {
724 writeString("{}"); 719 writeString("{}");
725 return true; 720 return true;
726 } 721 }
727 List keyValueList = new List(map.length * 2); 722 List keyValueList = new List(map.length * 2);
728 int i = 0; 723 int i = 0;
729 bool allStringKeys = true; 724 bool allStringKeys = true;
730 map.forEach((key, value) { 725 map.forEach((key, value) {
731 if (key is! String) { 726 if (key is! String) {
732 allStringKeys = false; 727 allStringKeys = false;
(...skipping 21 matching lines...) Expand all
754 * [Map] objects using the specified indent value. 749 * [Map] objects using the specified indent value.
755 * 750 *
756 * Subclasses should implement [writeIndentation]. 751 * Subclasses should implement [writeIndentation].
757 */ 752 */
758 abstract class _JsonPrettyPrintMixin implements _JsonStringifier { 753 abstract class _JsonPrettyPrintMixin implements _JsonStringifier {
759 int _indentLevel = 0; 754 int _indentLevel = 0;
760 755
761 /** 756 /**
762 * Add [indentLevel] indentations to the JSON output. 757 * Add [indentLevel] indentations to the JSON output.
763 */ 758 */
764 void writeIndentation(indentLevel); 759 void writeIndentation(int indentLevel);
765 760
766 void writeList(List list) { 761 void writeList(List list) {
767 if (list.isEmpty) { 762 if (list.isEmpty) {
768 writeString('[]'); 763 writeString('[]');
769 } else { 764 } else {
770 writeString('[\n'); 765 writeString('[\n');
771 _indentLevel++; 766 _indentLevel++;
772 writeIndentation(_indentLevel); 767 writeIndentation(_indentLevel);
773 writeObject(list[0]); 768 writeObject(list[0]);
774 for (int i = 1; i < list.length; i++) { 769 for (int i = 1; i < list.length; i++) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
831 * Convert object to a string. 826 * Convert object to a string.
832 * 827 *
833 * The [toEncodable] function is used to convert non-encodable objects 828 * The [toEncodable] function is used to convert non-encodable objects
834 * to encodable ones. 829 * to encodable ones.
835 * 830 *
836 * If [indent] is not `null`, the resulting JSON will be "pretty-printed" 831 * If [indent] is not `null`, the resulting JSON will be "pretty-printed"
837 * with newlines and indentation. The `indent` string is added as indentation 832 * with newlines and indentation. The `indent` string is added as indentation
838 * for each indentation level. It should only contain valid JSON whitespace 833 * for each indentation level. It should only contain valid JSON whitespace
839 * characters (space, tab, carriage return or line feed). 834 * characters (space, tab, carriage return or line feed).
840 */ 835 */
841 static String stringify(object, toEncodable(object), String indent) { 836 static String stringify(object, toEncodable(o), String indent) {
842 StringBuffer output = new StringBuffer(); 837 StringBuffer output = new StringBuffer();
843 printOn(object, output, toEncodable, indent); 838 printOn(object, output, toEncodable, indent);
844 return output.toString(); 839 return output.toString();
845 } 840 }
846 841
847 /** 842 /**
848 * Convert object to a string, and write the result to the [output] sink. 843 * Convert object to a string, and write the result to the [output] sink.
849 * 844 *
850 * The result is written piecemally to the sink. 845 * The result is written piecemally to the sink.
851 */ 846 */
852 static void printOn(object, StringSink output, toEncodable(object), 847 static void printOn(
853 String indent) { 848 object, StringSink output, toEncodable(o), String indent) {
854 var stringifier; 849 var stringifier;
855 if (indent == null) { 850 if (indent == null) {
856 stringifier = new _JsonStringStringifier(output, toEncodable); 851 stringifier = new _JsonStringStringifier(output, toEncodable);
857 } else { 852 } else {
858 stringifier = 853 stringifier =
859 new _JsonStringStringifierPretty(output, toEncodable, indent); 854 new _JsonStringStringifierPretty(output, toEncodable, indent);
860 } 855 }
861 stringifier.writeObject(object); 856 stringifier.writeObject(object);
862 } 857 }
863 858
864 void writeNumber(num number) { 859 void writeNumber(num number) {
865 _sink.write(number.toString()); 860 _sink.write(number.toString());
866 } 861 }
867 void writeString(String string) { 862 void writeString(String string) {
868 _sink.write(string); 863 _sink.write(string);
869 } 864 }
870 void writeStringSlice(String string, int start, int end) { 865 void writeStringSlice(String string, int start, int end) {
871 _sink.write(string.substring(start, end)); 866 _sink.write(string.substring(start, end));
872 } 867 }
873 void writeCharCode(int charCode) { 868 void writeCharCode(int charCode) {
874 _sink.writeCharCode(charCode); 869 _sink.writeCharCode(charCode);
875 } 870 }
876 } 871 }
877 872
878 class _JsonStringStringifierPretty extends _JsonStringStringifier 873 class _JsonStringStringifierPretty extends _JsonStringStringifier
879 with _JsonPrettyPrintMixin { 874 with _JsonPrettyPrintMixin {
880 final String _indent; 875 final String _indent;
881 876
882 _JsonStringStringifierPretty(StringSink sink, Function toEncodable, 877 _JsonStringStringifierPretty(StringSink sink, toEncodable(o), this._indent)
883 this._indent)
884 : super(sink, toEncodable); 878 : super(sink, toEncodable);
885 879
886 void writeIndentation(int count) { 880 void writeIndentation(int count) {
887 for (int i = 0; i < count; i++) writeString(_indent); 881 for (int i = 0; i < count; i++) writeString(_indent);
888 } 882 }
889 } 883 }
890 884
885 typedef void _AddChunk(Uint8List list, int start, int end);
886
891 /** 887 /**
892 * Specialization of [_JsonStringifier] that writes the JSON as UTF-8. 888 * Specialization of [_JsonStringifier] that writes the JSON as UTF-8.
893 * 889 *
894 * The JSON text is UTF-8 encoded and written to [Uint8List] buffers. 890 * The JSON text is UTF-8 encoded and written to [Uint8List] buffers.
895 * The buffers are then passed back to a user provided callback method. 891 * The buffers are then passed back to a user provided callback method.
896 */ 892 */
897 class _JsonUtf8Stringifier extends _JsonStringifier { 893 class _JsonUtf8Stringifier extends _JsonStringifier {
898 final int bufferSize; 894 final int bufferSize;
899 final Function addChunk; 895 final _AddChunk addChunk;
900 Uint8List buffer; 896 Uint8List buffer;
901 int index = 0; 897 int index = 0;
902 898
903 _JsonUtf8Stringifier(toEncodable, int bufferSize, this.addChunk) 899 _JsonUtf8Stringifier(toEncodable(o), int bufferSize, this.addChunk)
904 : this.bufferSize = bufferSize, 900 : this.bufferSize = bufferSize,
905 buffer = new Uint8List(bufferSize), 901 buffer = new Uint8List(bufferSize),
906 super(toEncodable); 902 super(toEncodable);
907 903
908 /** 904 /**
909 * Convert [object] to UTF-8 encoded JSON. 905 * Convert [object] to UTF-8 encoded JSON.
910 * 906 *
911 * Calls [addChunk] with slices of UTF-8 code units. 907 * Calls [addChunk] with slices of UTF-8 code units.
912 * These will typically have size [bufferSize], but may be shorter. 908 * These will typically have size [bufferSize], but may be shorter.
913 * The buffers are not reused, so the [addChunk] call may keep and reuse the 909 * The buffers are not reused, so the [addChunk] call may keep and reuse the
914 * chunks. 910 * chunks.
915 * 911 *
916 * If [indent] is non-`null`, the result will be "pretty-printed" with extra 912 * If [indent] is non-`null`, the result will be "pretty-printed" with extra
917 * newlines and indentation, using [indent] as the indentation. 913 * newlines and indentation, using [indent] as the indentation.
918 */ 914 */
919 static void stringify(Object object, 915 static void stringify(Object object,
920 List<int> indent, 916 List<int> indent,
921 toEncodableFunction(Object o), 917 toEncodable(o),
922 int bufferSize, 918 int bufferSize,
923 void addChunk(Uint8List chunk, int start, int end)) { 919 void addChunk(Uint8List chunk, int start, int end)) {
924 _JsonUtf8Stringifier stringifier; 920 _JsonUtf8Stringifier stringifier;
925 if (indent != null) { 921 if (indent != null) {
926 stringifier = new _JsonUtf8StringifierPretty(toEncodableFunction, indent, 922 stringifier = new _JsonUtf8StringifierPretty(toEncodable, indent,
927 bufferSize, addChunk); 923 bufferSize, addChunk);
928 } else { 924 } else {
929 stringifier = new _JsonUtf8Stringifier(toEncodableFunction, 925 stringifier = new _JsonUtf8Stringifier(toEncodable, bufferSize, addChunk);
930 bufferSize, addChunk);
931 } 926 }
932 stringifier.writeObject(object); 927 stringifier.writeObject(object);
933 stringifier.flush(); 928 stringifier.flush();
934 } 929 }
935 930
936 /** 931 /**
937 * Must be called at the end to push the last chunk to the [addChunk] 932 * Must be called at the end to push the last chunk to the [addChunk]
938 * callback. 933 * callback.
939 */ 934 */
940 void flush() { 935 void flush() {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 buffer[index++] = byte; 1025 buffer[index++] = byte;
1031 } 1026 }
1032 } 1027 }
1033 1028
1034 /** 1029 /**
1035 * Pretty-printing version of [_JsonUtf8Stringifier]. 1030 * Pretty-printing version of [_JsonUtf8Stringifier].
1036 */ 1031 */
1037 class _JsonUtf8StringifierPretty extends _JsonUtf8Stringifier 1032 class _JsonUtf8StringifierPretty extends _JsonUtf8Stringifier
1038 with _JsonPrettyPrintMixin { 1033 with _JsonPrettyPrintMixin {
1039 final List<int> indent; 1034 final List<int> indent;
1040 _JsonUtf8StringifierPretty(toEncodableFunction, this.indent, 1035 _JsonUtf8StringifierPretty(
1041 bufferSize, addChunk) 1036 toEncodable(o), this.indent,
1042 : super(toEncodableFunction, bufferSize, addChunk); 1037 bufferSize, void addChunk(Uint8List buffer, int start, int end))
1038 : super(toEncodable, bufferSize, addChunk);
1043 1039
1044 void writeIndentation(int count) { 1040 void writeIndentation(int count) {
1045 List<int> indent = this.indent; 1041 List<int> indent = this.indent;
1046 int indentLength = indent.length; 1042 int indentLength = indent.length;
1047 if (indentLength == 1) { 1043 if (indentLength == 1) {
1048 int char = indent[0]; 1044 int char = indent[0];
1049 while (count > 0) { 1045 while (count > 0) {
1050 writeByte(char); 1046 writeByte(char);
1051 count -= 1; 1047 count -= 1;
1052 } 1048 }
1053 return; 1049 return;
1054 } 1050 }
1055 while (count > 0) { 1051 while (count > 0) {
1056 count--; 1052 count--;
1057 int end = index + indentLength; 1053 int end = index + indentLength;
1058 if (end <= buffer.length) { 1054 if (end <= buffer.length) {
1059 buffer.setRange(index, end, indent); 1055 buffer.setRange(index, end, indent);
1060 index = end; 1056 index = end;
1061 } else { 1057 } else {
1062 for (int i = 0; i < indentLength; i++) { 1058 for (int i = 0; i < indentLength; i++) {
1063 writeByte(indent[i]); 1059 writeByte(indent[i]);
1064 } 1060 }
1065 } 1061 }
1066 } 1062 }
1067 } 1063 }
1068 } 1064 }
OLDNEW
« no previous file with comments | « sdk/lib/convert/html_escape.dart ('k') | sdk/lib/convert/line_splitter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698