Index: sdk/lib/convert/json.dart |
diff --git a/sdk/lib/convert/json.dart b/sdk/lib/convert/json.dart |
index df036a194a26173bb6415596234f11b86d43e741..36c638195c1cff0fa29c555cd851f900437ca9ab 100644 |
--- a/sdk/lib/convert/json.dart |
+++ b/sdk/lib/convert/json.dart |
@@ -53,8 +53,10 @@ class JsonCodec extends Codec<Object, String> { |
JsonDecoder get decoder => new JsonDecoder(null); |
} |
+typedef _Reviver(var key, var value); |
+ |
class _ReviverJsonCodec extends JsonCodec { |
- final Function _reviver; |
+ final _Reviver _reviver; |
_ReviverJsonCodec(this._reviver); |
Object decode(String str, {reviver(var key, var value)}) { |
@@ -66,7 +68,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 +101,58 @@ 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); |
+ |
+ /** |
+ * Starts a chunked conversion. |
+ * |
+ * The converter works more efficiently if the given [sink] is a |
+ * [StringConversionSink]. |
+ * |
+ * Returns a chunked-conversion sink that accepts at most one object. It is |
+ * an error to invoke `add` more than once on the returned sink. |
+ */ |
+ ChunkedConversionSink<Object> startChunkedConversion( |
+ ChunkedConversionSink<String> sink) { |
+ if (sink is! StringConversionSink) { |
+ sink = new StringConversionSink.from(sink); |
+ } |
+ return new _JsonEncoderSink(sink); |
+ } |
} |
-typedef _Reviver(var key, var value); |
+/** |
+ * 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 */ } |
+} |
/** |
- * 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 +164,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 +179,40 @@ 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<Object> sink) { |
+ return new _JsonDecoderSink(_reviver, sink); |
+ } |
+} |
+ |
+/** |
+ * 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(); |
+ } |
} |