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

Unified Diff: tool/input_sdk/lib/convert/json.dart

Issue 1965563003: Update dart:convert and dart:core Uri. (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: 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 side-by-side diff with in-line comments
Download patch
Index: tool/input_sdk/lib/convert/json.dart
diff --git a/tool/input_sdk/lib/convert/json.dart b/tool/input_sdk/lib/convert/json.dart
index 083d26e3c35e0f824872a38c0c1dd635d71ad45b..e80a9868fab20b1c881dc54f198c90467ac8c569 100644
--- a/tool/input_sdk/lib/convert/json.dart
+++ b/tool/input_sdk/lib/convert/json.dart
@@ -9,10 +9,10 @@ part of dart.convert;
*
* The [unsupportedObject] field holds that object that failed to be serialized.
*
- * If an object isn't directly serializable, the serializer calls the 'toJson'
+ * If an object isn't directly serializable, the serializer calls the `toJson`
* method on the object. If that call fails, the error will be stored in the
* [cause] field. If the call returns an object that isn't directly
- * serializable, the [cause] is be null.
+ * serializable, the [cause] is null.
*/
class JsonUnsupportedObjectError extends Error {
/** The object that could not be serialized. */
@@ -65,6 +65,11 @@ typedef _ToEncodable(var o);
/**
* A [JsonCodec] encodes JSON objects to strings and decodes strings to
* JSON objects.
+ *
+ * Examples:
+ *
+ * var encoded = JSON.encode([1, 2, { "a": null }]);
+ * var decoded = JSON.decode('["foo", { "bar": 499 }]');
*/
class JsonCodec extends Codec<Object, String> {
final _Reviver _reviver;
@@ -73,24 +78,22 @@ class JsonCodec extends Codec<Object, String> {
/**
* Creates a `JsonCodec` with the given reviver and encoding function.
*
- * The [reviver] function is called during decoding. It is invoked
- * once for each object or list property that has been parsed.
- * The `key` argument is either the
- * integer list index for a list property, the string map key for object
- * properties, or `null` for the final result.
+ * The [reviver] function is called during decoding. It is invoked once for
+ * each object or list property that has been parsed.
+ * The `key` argument is either the integer list index for a list property,
+ * the string map key for object properties, or `null` for the final result.
*
* If [reviver] is omitted, it defaults to returning the value argument.
*
* The [toEncodable] function is used during encoding. It is invoked for
- * values that are not directly encodable to a JSON1toE
- * string (a value that is not a number, boolean, string, null, list or a map
- * with string keys). The function must return an object that is directly
- * encodable. The elements of a returned list and values of a returned map
- * do not need be directly encodable, and if they aren't, `toEncodable` will
- * be used on them as well.
- * Please notice that it is possible to cause an infinite recursive
- * regress in this way, by effectively creating an infinite data structure
- * through repeated call to `toEncodable`.
+ * values that are not directly encodable to a string (a value that is not a
+ * number, boolean, string, null, list or a map with string keys). The
+ * function must return an object that is directly encodable. The elements of
+ * a returned list and values of a returned map do not need to be directly
+ * encodable, and if they aren't, `toEncodable` will be used on them as well.
+ * Please notice that it is possible to cause an infinite recursive regress
+ * in this way, by effectively creating an infinite data structure through
+ * repeated call to `toEncodable`.
*
* If [toEncodable] is omitted, it defaults to a function that returns the
* result of calling `.toJson()` on the unencodable object.
@@ -156,7 +159,7 @@ class JsonCodec extends Codec<Object, String> {
/**
* This class converts JSON objects to strings.
*/
-class JsonEncoder extends Converter<Object, String> {
+class JsonEncoder extends ChunkedConverter<Object, String, Object, String> {
/**
* The string used for indention.
*
@@ -215,14 +218,14 @@ class JsonEncoder extends Converter<Object, String> {
* Converts [object] to a JSON [String].
*
* Directly serializable values are [num], [String], [bool], and [Null], as
- * well as some [List] and [Map] values.
- * For [List], the elements must all be serializable.
- * For [Map], the keys must be [String] and the values must be serializable.
+ * well as some [List] and [Map] values. For [List], the elements must all be
+ * serializable. For [Map], the keys must be [String] and the values must be
+ * serializable.
*
- * If a value is any other type is attempted serialized, the conversion
- * function provided in the constructor is invoked with the object as argument
- * and the result, which must be a directly serializable value,
- * is serialized instead of the original value.
+ * If a value of any other type is attempted to be serialized, the
+ * `toEncodable` function provided in the constructor is called with the value
+ * as argument. The result, which must be a directly serializable value, is
+ * serialized instead of the original value.
*
* If the conversion throws, or returns a value that is not directly
* serializable, a [JsonUnsupportedObjectError] exception is thrown.
@@ -262,7 +265,7 @@ class JsonEncoder extends Converter<Object, String> {
return new _JsonEncoderSink(sink, _toEncodable, indent);
}
- // Override the base-classes bind, to provide a better type.
+ // Override the base class's bind, to provide a better type.
Stream<String> bind(Stream<Object> stream) => super.bind(stream);
Converter<Object, dynamic> fuse(Converter<String, dynamic> other) {
@@ -280,7 +283,8 @@ class JsonEncoder extends Converter<Object, String> {
* a JSON string, and then UTF-8 encoding the string, but without
* creating an intermediate string.
*/
-class JsonUtf8Encoder extends Converter<Object, List<int>> {
+class JsonUtf8Encoder extends
+ ChunkedConverter<Object, List<int>, Object, List<int>> {
/** Default buffer size used by the JSON-to-UTF-8 encoder. */
static const int DEFAULT_BUFFER_SIZE = 256;
/** Indentation used in pretty-print mode, `null` if not pretty. */
@@ -299,20 +303,21 @@ class JsonUtf8Encoder extends Converter<Object, List<int>> {
* If `indent` contains characters that are not valid JSON whitespace
* characters, the result will not be valid JSON. JSON whitespace characters
* are space (U+0020), tab (U+0009), line feed (U+000a) and carriage return
- * (U+000d) (ECMA 404).
+ * (U+000d) ([ECMA
+ * 404](http://www.ecma-international.org/publications/standards/Ecma-404.htm)).
*
* The [bufferSize] is the size of the internal buffers used to collect
* UTF-8 code units.
* If using [startChunkedConversion], it will be the size of the chunks.
*
- * The JSON encoder handles numbers, strings, booleans, null, lists and
- * maps directly.
+ * The JSON encoder handles numbers, strings, booleans, null, lists and maps
+ * directly.
*
- * Any other object is attempted converted by [toEncodable] to an
- * object that is of one of the convertible types.
+ * Any other object is attempted converted by [toEncodable] to an object that
+ * is of one of the convertible types.
*
- * If [toEncodable] is omitted, it defaults to calling `.toJson()` on
- * the object.
+ * If [toEncodable] is omitted, it defaults to calling `.toJson()` on the
+ * object.
*/
JsonUtf8Encoder([String indent,
toEncodable(Object object),
@@ -386,7 +391,7 @@ class JsonUtf8Encoder extends Converter<Object, List<int>> {
_indent, _bufferSize);
}
- // Override the base-classes bind, to provide a better type.
+ // Override the base class's bind, to provide a better type.
Stream<List<int>> bind(Stream<Object> stream) {
return super.bind(stream);
}
@@ -469,7 +474,7 @@ class _JsonUtf8EncoderSink extends ChunkedConversionSink<Object> {
/**
* This class parses JSON strings and builds the corresponding objects.
*/
-class JsonDecoder extends Converter<String, Object> {
+class JsonDecoder extends ChunkedConverter<String, Object, String, Object> {
final _Reviver _reviver;
/**
* Constructs a new JsonDecoder.
@@ -482,8 +487,8 @@ class JsonDecoder extends Converter<String, 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
- * JSON values.
+ * [List]s of parsed JSON values or [Map]s from [String] to parsed JSON
+ * values.
*
* If `this` was initialized with a reviver, then the parsing operation
* invokes the reviver on every object or list property that has been parsed.
@@ -496,14 +501,13 @@ class JsonDecoder extends Converter<String, Object> {
dynamic convert(String input) => _parseJson(input, _reviver);
/**
- * Starts a conversion from a chunked JSON string to its corresponding
- * object.
+ * Starts a conversion from a chunked JSON string to its corresponding object.
*
* The output [sink] receives exactly one decoded element through `add`.
*/
external StringConversionSink startChunkedConversion(Sink<Object> sink);
- // Override the base-classes bind, to provide a better type.
+ // Override the base class's bind, to provide a better type.
Stream<Object> bind(Stream<String> stream) => super.bind(stream);
}
@@ -613,9 +617,8 @@ abstract class _JsonStringifier {
/**
* Check if an encountered object is already being traversed.
*
- * Records the object if it isn't already seen.
- * Should have a matching call to [_removeSeen] when the object
- * is no longer being traversed.
+ * Records the object if it isn't already seen. Should have a matching call to
+ * [_removeSeen] when the object is no longer being traversed.
*/
void _checkCycle(object) {
for (int i = 0; i < _seen.length; i++) {
@@ -627,7 +630,7 @@ abstract class _JsonStringifier {
}
/**
- * Removes object from the list of currently traversed objects.
+ * Remove [object] from the list of currently traversed objects.
*
* Should be called in the opposite order of the matching [_checkCycle]
* calls.
@@ -639,10 +642,10 @@ abstract class _JsonStringifier {
}
/**
- * Writes an object.
+ * Write an object.
*
- * If the object isn't directly encodable, the [_toEncodable] function
- * gets one chance to return a replacement which is encodable.
+ * If [object] isn't directly encodable, the [_toEncodable] function gets one
+ * chance to return a replacement which is encodable.
*/
void writeObject(object) {
// Tries stringifying object directly. If it's not a simple value, List or
@@ -662,7 +665,7 @@ abstract class _JsonStringifier {
}
/**
- * Serializes a [num], [String], [bool], [Null], [List] or [Map] value.
+ * Serialize a [num], [String], [bool], [Null], [List] or [Map] value.
*
* Returns true if the value is one of these types, and false if not.
* If a value is both a [List] and a [Map], it's serialized as a [List].
@@ -693,15 +696,16 @@ abstract class _JsonStringifier {
return true;
} else if (object is Map) {
_checkCycle(object);
- writeMap(object);
+ // writeMap can fail if keys are not all strings.
+ var success = writeMap(object);
_removeSeen(object);
- return true;
+ return success;
} else {
return false;
}
}
- /** Serializes a [List]. */
+ /** Serialize a [List]. */
void writeList(List list) {
writeString('[');
if (list.length > 0) {
@@ -714,18 +718,34 @@ abstract class _JsonStringifier {
writeString(']');
}
- /** Serializes a [Map]. */
- void writeMap(Map<String, Object> map) {
+ /** Serialize a [Map]. */
+ bool writeMap(Map<String, Object> map) {
+ if (map.isEmpty) {
+ writeString("{}");
+ return true;
+ }
+ List keyValueList = new List(map.length * 2);
+ int i = 0;
+ bool allStringKeys = true;
+ map.forEach((key, value) {
+ if (key is! String) {
+ allStringKeys = false;
+ }
+ keyValueList[i++] = key;
+ keyValueList[i++] = value;
+ });
+ if (!allStringKeys) return false;
writeString('{');
String separator = '"';
- map.forEach((String key, value) {
+ for (int i = 0; i < keyValueList.length; i += 2) {
writeString(separator);
separator = ',"';
- writeStringContent(key);
+ writeStringContent(keyValueList[i]);
writeString('":');
- writeObject(value);
- });
+ writeObject(keyValueList[i + 1]);
+ }
writeString('}');
+ return true;
}
}
@@ -763,29 +783,39 @@ abstract class _JsonPrettyPrintMixin implements _JsonStringifier {
}
}
- void writeMap(Map map) {
+ bool writeMap(Map map) {
if (map.isEmpty) {
- writeString('{}');
- } else {
- writeString('{\n');
- _indentLevel++;
- bool first = true;
- map.forEach((String key, Object value) {
- if (!first) {
- writeString(",\n");
- }
- writeIndentation(_indentLevel);
- writeString('"');
- writeStringContent(key);
- writeString('": ');
- writeObject(value);
- first = false;
- });
- writeString('\n');
- _indentLevel--;
+ writeString("{}");
+ return true;
+ }
+ List keyValueList = new List(map.length * 2);
+ int i = 0;
+ bool allStringKeys = true;
+ map.forEach((key, value) {
+ if (key is! String) {
+ allStringKeys = false;
+ }
+ keyValueList[i++] = key;
+ keyValueList[i++] = value;
+ });
+ if (!allStringKeys) return false;
+ writeString('{\n');
+ _indentLevel++;
+ String separator = "";
+ for (int i = 0; i < keyValueList.length; i += 2) {
+ writeString(separator);
+ separator = ",\n";
writeIndentation(_indentLevel);
- writeString('}');
+ writeString('"');
+ writeStringContent(keyValueList[i]);
+ writeString('": ');
+ writeObject(keyValueList[i + 1]);
}
+ writeString('\n');
+ _indentLevel--;
+ writeIndentation(_indentLevel);
+ writeString('}');
+ return true;
}
}
@@ -873,19 +903,18 @@ class _JsonUtf8Stringifier extends _JsonStringifier {
_JsonUtf8Stringifier(toEncodable, int bufferSize, this.addChunk)
: this.bufferSize = bufferSize,
buffer = new Uint8List(bufferSize),
- super(toEncodable)
- ;
+ super(toEncodable);
/**
* Convert [object] to UTF-8 encoded JSON.
*
* Calls [addChunk] with slices of UTF-8 code units.
* These will typically have size [bufferSize], but may be shorter.
- * The buffers are not reused, so the [addChunk] call may keep and reuse
- * the chunks.
+ * The buffers are not reused, so the [addChunk] call may keep and reuse the
+ * chunks.
*
- * If [indent] is non-`null`, the result will be "pretty-printed" with
- * extra newlines and indentation, using [indent] as the indentation.
+ * If [indent] is non-`null`, the result will be "pretty-printed" with extra
+ * newlines and indentation, using [indent] as the indentation.
*/
static void stringify(Object object,
List<int> indent,

Powered by Google App Engine
This is Rietveld 408576698