Index: sdk/lib/convert/json.dart |
diff --git a/sdk/lib/convert/json.dart b/sdk/lib/convert/json.dart |
index df036a194a26173bb6415596234f11b86d43e741..f0455d911ef544841eaf47898bc406f996aa856b 100644 |
--- a/sdk/lib/convert/json.dart |
+++ b/sdk/lib/convert/json.dart |
@@ -66,7 +66,7 @@ class _ReviverJsonCodec extends JsonCodec { |
} |
/** |
- * A [JsonEncoder] converts JSON objects to strings. |
+ * This class converts JSON objects to strings. |
*/ |
class JsonEncoder extends Converter<Object, String> { |
JsonEncoder(); |
@@ -99,13 +99,54 @@ class JsonEncoder extends Converter<Object, String> { |
* serialized, the new values may or may not be reflected in the result. |
*/ |
String convert(Object o) => OLD_JSON_LIB.stringify(o); |
+ |
+ ChunkedConversionSink<Object> startChunkedConversion( |
+ ChunkedConversionSink sink) { |
+ return new _JsonEncoderSink(sink.adaptTo(outputInterface)); |
+ } |
+ |
+ ChunkedConversionInterface get inputInterface => |
+ ChunkedConversionSink.INTERFACE; |
+ ChunkedConversionInterface get outputInterface => |
+ StringConversionSink.INTERFACE; |
+} |
+ |
+/** |
+ * Implements the chunked conversion from object to its JSON representation. |
+ * |
+ * The sink only accepts one value, but will produce output in a chunked way. |
+ */ |
+class _JsonEncoderSink extends ChunkedConversionSink<Object> { |
+ final StringConversionSink _sink; |
+ bool _isDone = false; |
+ |
+ _JsonEncoderSink(this._sink); |
+ |
+ /** |
+ * Encodes the given object [o]. |
+ * |
+ * It is an error to invoke this method more than once on any instance. While |
+ * this makes the input effectly non-chunked the output will be generated in |
+ * a chunked way. |
+ */ |
+ void add(Object o) { |
+ if (_isDone) { |
+ throw new StateError("Only one call to add allowed"); |
+ } |
+ _isDone = true; |
+ ClosableStringSink stringSink = _sink.asStringSink(); |
+ OLD_JSON_LIB.printOn(o, stringSink); |
+ stringSink.close(); |
+ } |
+ |
+ void close() { /* do nothing */ } |
} |
-typedef _Reviver(var key, var value); |
+typedef _Reviver(var key, var value); |
/** |
- * A [JsonDecoder] parses JSON strings and builds the corresponding objects. |
+ * This class parses JSON strings and builds the corresponding objects. |
*/ |
class JsonDecoder extends Converter<String, Object> { |
final _Reviver _reviver; |
@@ -117,7 +158,7 @@ class JsonDecoder extends Converter<String, Object> { |
JsonDecoder(reviver(var key, var value)) : this._reviver = reviver; |
/** |
- * Converts the given Json-string [input] to its corresponding object. |
+ * Converts the given JSON-string [input] to its corresponding object. |
* |
* Parsed JSON values are of the types [num], [String], [bool], [Null], |
* [List]s of parsed JSON values or [Map]s from [String] to parsed |
@@ -132,4 +173,46 @@ class JsonDecoder extends Converter<String, Object> { |
* Throws [FormatException] if the input is not valid JSON text. |
*/ |
Object convert(String input) => OLD_JSON_LIB.parse(input, _reviver); |
+ |
+ /** |
+ * Starts a conversion from a chunked JSON string to its corresponding |
+ * object. |
+ * |
+ * The output [sink] receives exactly one decoded element through `add`. |
+ */ |
+ StringConversionSink startChunkedConversion(ChunkedConversionSink sink) { |
+ // In theory we don't need to go through the `adaptTo` dance, but it |
+ // shouldn't hurt. |
+ return new _JsonDecoderSink(_reviver, sink.adaptTo(outputInterface)); |
+ } |
+ |
+ ChunkedConversionInterface get inputInterface => |
+ StringConversionSink.INTERFACE; |
+ ChunkedConversionInterface get outputInterface => |
+ ChunkedConversionSink.INTERFACE; |
+} |
+ |
+/** |
+ * Implements the chunked conversion from a JSON string to its corresponding |
+ * object. |
+ * |
+ * The sink only creates one object, but its input can be chunked. |
+ */ |
+// TODO(floitsch): don't accumulate everything before starting to decode. |
+class _JsonDecoderSink extends _StringSinkConversionSink { |
+ final _Reviver _reviver; |
+ final ChunkedConversionSink<Object> _chunkedSink; |
+ |
+ _JsonDecoderSink(this._reviver, this._chunkedSink) |
+ : super(new StringBuffer()); |
+ |
+ void close() { |
+ super.close(); |
+ StringBuffer buffer = _stringSink; |
+ String accumulated = buffer.toString(); |
+ buffer.clear(); |
+ Object decoded = OLD_JSON_LIB.parse(accumulated, _reviver); |
+ _chunkedSink.add(decoded); |
+ _chunkedSink.close(); |
+ } |
} |