OLD | NEW |
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 * An instance of the default implementation of the [JsonCodec]. | 8 * An instance of the default implementation of the [JsonCodec]. |
9 * | 9 * |
10 * This instance provides a convenient access to the most common JSON | 10 * This instance provides a convenient access to the most common JSON |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 * The default [reviver] (when not provided) is the identity function. | 46 * The default [reviver] (when not provided) is the identity function. |
47 */ | 47 */ |
48 Object decode(String str, {reviver(var key, var value)}) { | 48 Object decode(String str, {reviver(var key, var value)}) { |
49 return new JsonDecoder(reviver).convert(str); | 49 return new JsonDecoder(reviver).convert(str); |
50 } | 50 } |
51 | 51 |
52 JsonEncoder get encoder => new JsonEncoder(); | 52 JsonEncoder get encoder => new JsonEncoder(); |
53 JsonDecoder get decoder => new JsonDecoder(null); | 53 JsonDecoder get decoder => new JsonDecoder(null); |
54 } | 54 } |
55 | 55 |
| 56 typedef _Reviver(var key, var value); |
| 57 |
56 class _ReviverJsonCodec extends JsonCodec { | 58 class _ReviverJsonCodec extends JsonCodec { |
57 final Function _reviver; | 59 final _Reviver _reviver; |
58 _ReviverJsonCodec(this._reviver); | 60 _ReviverJsonCodec(this._reviver); |
59 | 61 |
60 Object decode(String str, {reviver(var key, var value)}) { | 62 Object decode(String str, {reviver(var key, var value)}) { |
61 if (reviver == null) reviver = _reviver; | 63 if (reviver == null) reviver = _reviver; |
62 return new JsonDecoder(reviver).convert(str); | 64 return new JsonDecoder(reviver).convert(str); |
63 } | 65 } |
64 | 66 |
65 JsonDecoder get decoder => new JsonDecoder(_reviver); | 67 JsonDecoder get decoder => new JsonDecoder(_reviver); |
66 } | 68 } |
67 | 69 |
68 /** | 70 /** |
69 * A [JsonEncoder] converts JSON objects to strings. | 71 * This class converts JSON objects to strings. |
70 */ | 72 */ |
71 class JsonEncoder extends Converter<Object, String> { | 73 class JsonEncoder extends Converter<Object, String> { |
72 JsonEncoder(); | 74 JsonEncoder(); |
73 | 75 |
74 /** | 76 /** |
75 * Converts the given object [o] to its JSON representation. | 77 * Converts the given object [o] to its JSON representation. |
76 * | 78 * |
77 * Directly serializable values are [num], [String], [bool], and [Null], as | 79 * Directly serializable values are [num], [String], [bool], and [Null], as |
78 * well as some [List] and [Map] values. | 80 * well as some [List] and [Map] values. |
79 * For [List], the elements must all be serializable. | 81 * For [List], the elements must all be serializable. |
(...skipping 12 matching lines...) Expand all Loading... |
92 * If a [List] or [Map] contains a reference to itself, directly or through | 94 * If a [List] or [Map] contains a reference to itself, directly or through |
93 * other lists or maps, it cannot be serialized and a [JsonCyclicError] is | 95 * other lists or maps, it cannot be serialized and a [JsonCyclicError] is |
94 * thrown. | 96 * thrown. |
95 * | 97 * |
96 * Json Objects should not change during serialization. | 98 * Json Objects should not change during serialization. |
97 * If an object is serialized more than once, [stringify] is allowed to cache | 99 * If an object is serialized more than once, [stringify] is allowed to cache |
98 * the JSON text for it. I.e., if an object changes after it is first | 100 * the JSON text for it. I.e., if an object changes after it is first |
99 * serialized, the new values may or may not be reflected in the result. | 101 * serialized, the new values may or may not be reflected in the result. |
100 */ | 102 */ |
101 String convert(Object o) => OLD_JSON_LIB.stringify(o); | 103 String convert(Object o) => OLD_JSON_LIB.stringify(o); |
| 104 |
| 105 /** |
| 106 * Starts a chunked conversion. |
| 107 * |
| 108 * The converter works more efficiently if the given [sink] is a |
| 109 * [StringConversionSink]. |
| 110 * |
| 111 * Returns a chunked-conversion sink that accepts at most one object. It is |
| 112 * an error to invoke `add` more than once on the returned sink. |
| 113 */ |
| 114 ChunkedConversionSink<Object> startChunkedConversion( |
| 115 ChunkedConversionSink<String> sink) { |
| 116 if (sink is! StringConversionSink) { |
| 117 sink = new StringConversionSink.from(sink); |
| 118 } |
| 119 return new _JsonEncoderSink(sink); |
| 120 } |
102 } | 121 } |
103 | 122 |
104 typedef _Reviver(var key, var value); | 123 /** |
| 124 * Implements the chunked conversion from object to its JSON representation. |
| 125 * |
| 126 * The sink only accepts one value, but will produce output in a chunked way. |
| 127 */ |
| 128 class _JsonEncoderSink extends ChunkedConversionSink<Object> { |
| 129 final StringConversionSink _sink; |
| 130 bool _isDone = false; |
105 | 131 |
| 132 _JsonEncoderSink(this._sink); |
| 133 |
| 134 /** |
| 135 * Encodes the given object [o]. |
| 136 * |
| 137 * It is an error to invoke this method more than once on any instance. While |
| 138 * this makes the input effectly non-chunked the output will be generated in |
| 139 * a chunked way. |
| 140 */ |
| 141 void add(Object o) { |
| 142 if (_isDone) { |
| 143 throw new StateError("Only one call to add allowed"); |
| 144 } |
| 145 _isDone = true; |
| 146 ClosableStringSink stringSink = _sink.asStringSink(); |
| 147 OLD_JSON_LIB.printOn(o, stringSink); |
| 148 stringSink.close(); |
| 149 } |
| 150 |
| 151 void close() { /* do nothing */ } |
| 152 } |
106 | 153 |
107 /** | 154 /** |
108 * A [JsonDecoder] parses JSON strings and builds the corresponding objects. | 155 * This class parses JSON strings and builds the corresponding objects. |
109 */ | 156 */ |
110 class JsonDecoder extends Converter<String, Object> { | 157 class JsonDecoder extends Converter<String, Object> { |
111 final _Reviver _reviver; | 158 final _Reviver _reviver; |
112 /** | 159 /** |
113 * Constructs a new JsonDecoder. | 160 * Constructs a new JsonDecoder. |
114 * | 161 * |
115 * The [reviver] may be `null`. | 162 * The [reviver] may be `null`. |
116 */ | 163 */ |
117 JsonDecoder(reviver(var key, var value)) : this._reviver = reviver; | 164 JsonDecoder(reviver(var key, var value)) : this._reviver = reviver; |
118 | 165 |
119 /** | 166 /** |
120 * Converts the given Json-string [input] to its corresponding object. | 167 * Converts the given JSON-string [input] to its corresponding object. |
121 * | 168 * |
122 * Parsed JSON values are of the types [num], [String], [bool], [Null], | 169 * Parsed JSON values are of the types [num], [String], [bool], [Null], |
123 * [List]s of parsed JSON values or [Map]s from [String] to parsed | 170 * [List]s of parsed JSON values or [Map]s from [String] to parsed |
124 * JSON values. | 171 * JSON values. |
125 * | 172 * |
126 * If `this` was initialized with a reviver, then the parsing operation | 173 * If `this` was initialized with a reviver, then the parsing operation |
127 * invokes the reviver on every object or list property that has been parsed. | 174 * invokes the reviver on every object or list property that has been parsed. |
128 * The arguments are the property name ([String]) or list index ([int]), and | 175 * The arguments are the property name ([String]) or list index ([int]), and |
129 * the value is the parsed value. The return value of the reviver is used as | 176 * the value is the parsed value. The return value of the reviver is used as |
130 * the value of that property instead the parsed value. | 177 * the value of that property instead the parsed value. |
131 * | 178 * |
132 * Throws [FormatException] if the input is not valid JSON text. | 179 * Throws [FormatException] if the input is not valid JSON text. |
133 */ | 180 */ |
134 Object convert(String input) => OLD_JSON_LIB.parse(input, _reviver); | 181 Object convert(String input) => OLD_JSON_LIB.parse(input, _reviver); |
| 182 |
| 183 /** |
| 184 * Starts a conversion from a chunked JSON string to its corresponding |
| 185 * object. |
| 186 * |
| 187 * The output [sink] receives exactly one decoded element through `add`. |
| 188 */ |
| 189 StringConversionSink startChunkedConversion( |
| 190 ChunkedConversionSink<Object> sink) { |
| 191 return new _JsonDecoderSink(_reviver, sink); |
| 192 } |
135 } | 193 } |
| 194 |
| 195 /** |
| 196 * Implements the chunked conversion from a JSON string to its corresponding |
| 197 * object. |
| 198 * |
| 199 * The sink only creates one object, but its input can be chunked. |
| 200 */ |
| 201 // TODO(floitsch): don't accumulate everything before starting to decode. |
| 202 class _JsonDecoderSink extends _StringSinkConversionSink { |
| 203 final _Reviver _reviver; |
| 204 final ChunkedConversionSink<Object> _chunkedSink; |
| 205 |
| 206 _JsonDecoderSink(this._reviver, this._chunkedSink) |
| 207 : super(new StringBuffer()); |
| 208 |
| 209 void close() { |
| 210 super.close(); |
| 211 StringBuffer buffer = _stringSink; |
| 212 String accumulated = buffer.toString(); |
| 213 buffer.clear(); |
| 214 Object decoded = OLD_JSON_LIB.parse(accumulated, _reviver); |
| 215 _chunkedSink.add(decoded); |
| 216 _chunkedSink.close(); |
| 217 } |
| 218 } |
OLD | NEW |