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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 | 59 |
60 Object decode(String str, {reviver(var key, var value)}) { | 60 Object decode(String str, {reviver(var key, var value)}) { |
61 if (reviver == null) reviver = _reviver; | 61 if (reviver == null) reviver = _reviver; |
62 return new JsonDecoder(reviver).convert(str); | 62 return new JsonDecoder(reviver).convert(str); |
63 } | 63 } |
64 | 64 |
65 JsonDecoder get decoder => new JsonDecoder(_reviver); | 65 JsonDecoder get decoder => new JsonDecoder(_reviver); |
66 } | 66 } |
67 | 67 |
68 /** | 68 /** |
69 * A [JsonEncoder] converts JSON objects to strings. | 69 * This class converts JSON objects to strings. |
70 */ | 70 */ |
71 class JsonEncoder extends Converter<Object, String> { | 71 class JsonEncoder extends Converter<Object, String> { |
72 JsonEncoder(); | 72 JsonEncoder(); |
73 | 73 |
74 /** | 74 /** |
75 * Converts the given object [o] to its JSON representation. | 75 * Converts the given object [o] to its JSON representation. |
76 * | 76 * |
77 * Directly serializable values are [num], [String], [bool], and [Null], as | 77 * Directly serializable values are [num], [String], [bool], and [Null], as |
78 * well as some [List] and [Map] values. | 78 * well as some [List] and [Map] values. |
79 * For [List], the elements must all be serializable. | 79 * 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 | 92 * 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 | 93 * other lists or maps, it cannot be serialized and a [JsonCyclicError] is |
94 * thrown. | 94 * thrown. |
95 * | 95 * |
96 * Json Objects should not change during serialization. | 96 * Json Objects should not change during serialization. |
97 * If an object is serialized more than once, [stringify] is allowed to cache | 97 * 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 | 98 * 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. | 99 * serialized, the new values may or may not be reflected in the result. |
100 */ | 100 */ |
101 String convert(Object o) => OLD_JSON_LIB.stringify(o); | 101 String convert(Object o) => OLD_JSON_LIB.stringify(o); |
| 102 |
| 103 ChunkedConversionSink<Object> startChunkedConversion( |
| 104 ChunkedConversionSink sink) { |
| 105 return new _JsonEncoderSink(sink.adaptTo(outputInterface)); |
| 106 } |
| 107 |
| 108 ChunkedConversionInterface get inputInterface => |
| 109 ChunkedConversionSink.INTERFACE; |
| 110 ChunkedConversionInterface get outputInterface => |
| 111 StringConversionSink.INTERFACE; |
102 } | 112 } |
103 | 113 |
| 114 /** |
| 115 * Implements the chunked conversion from object to its JSON representation. |
| 116 * |
| 117 * The sink only accepts one value, but will produce output in a chunked way. |
| 118 */ |
| 119 class _JsonEncoderSink extends ChunkedConversionSink<Object> { |
| 120 final StringConversionSink _sink; |
| 121 bool _isDone = false; |
| 122 |
| 123 _JsonEncoderSink(this._sink); |
| 124 |
| 125 /** |
| 126 * Encodes the given object [o]. |
| 127 * |
| 128 * It is an error to invoke this method more than once on any instance. While |
| 129 * this makes the input effectly non-chunked the output will be generated in |
| 130 * a chunked way. |
| 131 */ |
| 132 void add(Object o) { |
| 133 if (_isDone) { |
| 134 throw new StateError("Only one call to add allowed"); |
| 135 } |
| 136 _isDone = true; |
| 137 ClosableStringSink stringSink = _sink.asStringSink(); |
| 138 OLD_JSON_LIB.printOn(o, stringSink); |
| 139 stringSink.close(); |
| 140 } |
| 141 |
| 142 void close() { /* do nothing */ } |
| 143 } |
| 144 |
| 145 |
104 typedef _Reviver(var key, var value); | 146 typedef _Reviver(var key, var value); |
105 | 147 |
106 | |
107 /** | 148 /** |
108 * A [JsonDecoder] parses JSON strings and builds the corresponding objects. | 149 * This class parses JSON strings and builds the corresponding objects. |
109 */ | 150 */ |
110 class JsonDecoder extends Converter<String, Object> { | 151 class JsonDecoder extends Converter<String, Object> { |
111 final _Reviver _reviver; | 152 final _Reviver _reviver; |
112 /** | 153 /** |
113 * Constructs a new JsonDecoder. | 154 * Constructs a new JsonDecoder. |
114 * | 155 * |
115 * The [reviver] may be `null`. | 156 * The [reviver] may be `null`. |
116 */ | 157 */ |
117 JsonDecoder(reviver(var key, var value)) : this._reviver = reviver; | 158 JsonDecoder(reviver(var key, var value)) : this._reviver = reviver; |
118 | 159 |
119 /** | 160 /** |
120 * Converts the given Json-string [input] to its corresponding object. | 161 * Converts the given JSON-string [input] to its corresponding object. |
121 * | 162 * |
122 * Parsed JSON values are of the types [num], [String], [bool], [Null], | 163 * 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 | 164 * [List]s of parsed JSON values or [Map]s from [String] to parsed |
124 * JSON values. | 165 * JSON values. |
125 * | 166 * |
126 * If `this` was initialized with a reviver, then the parsing operation | 167 * 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. | 168 * 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 | 169 * 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 | 170 * 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. | 171 * the value of that property instead the parsed value. |
131 * | 172 * |
132 * Throws [FormatException] if the input is not valid JSON text. | 173 * Throws [FormatException] if the input is not valid JSON text. |
133 */ | 174 */ |
134 Object convert(String input) => OLD_JSON_LIB.parse(input, _reviver); | 175 Object convert(String input) => OLD_JSON_LIB.parse(input, _reviver); |
| 176 |
| 177 /** |
| 178 * Starts a conversion from a chunked JSON string to its corresponding |
| 179 * object. |
| 180 * |
| 181 * The output [sink] receives exactly one decoded element through `add`. |
| 182 */ |
| 183 StringConversionSink startChunkedConversion(ChunkedConversionSink sink) { |
| 184 // In theory we don't need to go through the `adaptTo` dance, but it |
| 185 // shouldn't hurt. |
| 186 return new _JsonDecoderSink(_reviver, sink.adaptTo(outputInterface)); |
| 187 } |
| 188 |
| 189 ChunkedConversionInterface get inputInterface => |
| 190 StringConversionSink.INTERFACE; |
| 191 ChunkedConversionInterface get outputInterface => |
| 192 ChunkedConversionSink.INTERFACE; |
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 |