Chromium Code Reviews| Index: sdk/lib/json/json.dart |
| diff --git a/sdk/lib/json/json.dart b/sdk/lib/json/json.dart |
| index 8bd8ab215ebf6e72b5b6ecba08cbfe5bf9f97687..8cbf28bef21cf9fa17c080cd81870962643ad7e2 100644 |
| --- a/sdk/lib/json/json.dart |
| +++ b/sdk/lib/json/json.dart |
| @@ -9,6 +9,7 @@ |
| library dart.json; |
| import "dart:convert"; |
| +import "dart:collection" show HashSet; |
| export "dart:convert" show JsonUnsupportedObjectError, JsonCyclicError; |
| // JSON parsing and serialization. |
| @@ -44,27 +45,30 @@ parse(String json, [reviver(var key, var value)]) { |
| * 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, a "toJson()" method |
| - * is invoked on the object and the result, which must be a directly |
| - * serializable value, is serialized instead of the original value. |
| + * If a value is any other type is attempted serialized, the [convert] method |
| + * is called with the object as argument, and the result, which must be a |
| + * directly serializable value, is serialized instead of the original value. |
| + * If [convert] is omitted, the default is to call `object.toJson()` on the |
| + * object. |
| * |
| - * If the object does not support this method, throws, or returns a |
| - * value that is not directly serializable, a [JsonUnsupportedObjectError] |
| - * exception is thrown. If the call throws (including the case where there |
| - * is no nullary "toJson" method, the error is caught and stored in the |
| + * If the conversion throws, or returns a value that is not directly |
| + * serializable, a [JsonUnsupportedObjectError] exception is thrown. |
| + * If the call throws (including the case where there |
| + * is no nullary "toJson" method), the error is caught and stored in the |
| * [JsonUnsupportedObjectError]'s [:cause:] field. |
| * |
| * If a [List] or [Map] contains a reference to itself, directly or through |
| * other lists or maps, it cannot be serialized and a [JsonCyclicError] is |
| * thrown. |
| * |
| - * Json Objects should not change during serialization. |
| + * The objects being serialized should not change during serialization. |
| * If an object is serialized more than once, [stringify] is allowed to cache |
| * the JSON text for it. I.e., if an object changes after it is first |
| * serialized, the new values may or may not be reflected in the result. |
| */ |
| -String stringify(Object object) { |
| - return _JsonStringifier.stringify(object); |
| +String stringify(Object object, [convert(object)]) { |
|
floitsch
2013/10/04 15:25:08
You don't have the latest version (which now has d
Lasse Reichstein Nielsen
2013/10/07 12:46:59
Merging .... please hold. :)
I don't want to supp
|
| + if (convert == null) convert = _defaultConvert; |
| + return _JsonStringifier.stringify(object, convert); |
| } |
| /** |
| @@ -76,8 +80,9 @@ String stringify(Object object) { |
| * If serialization fails by throwing, some data might have been added to |
| * [output], but it won't contain valid JSON text. |
| */ |
| -void printOn(Object object, StringSink output) { |
| - return _JsonStringifier.printOn(object, output); |
| +void printOn(Object object, StringSink output, [ convert(object) ]) { |
| + if (convert == null) convert = _defaultConvert; |
| + return _JsonStringifier.printOn(object, output, convert); |
| } |
| //// Implementation /////////////////////////////////////////////////////////// |
| @@ -623,22 +628,25 @@ class JsonParser { |
| } |
| } |
| +Object _defaultConvert(object) => object.toJson(); |
| class _JsonStringifier { |
| - StringSink sink; |
| - List<Object> seen; // TODO: that should be identity set. |
| + final Function converter; |
| + final StringSink sink; |
| + final Set<Object> seen; |
| - _JsonStringifier(this.sink) : seen = []; |
| + _JsonStringifier(this.sink, this.converter) |
| + : this.seen = new HashSet.identity(); |
| - static String stringify(final object) { |
| + static String stringify(final object, convert(object)) { |
| StringBuffer output = new StringBuffer(); |
| - _JsonStringifier stringifier = new _JsonStringifier(output); |
| + _JsonStringifier stringifier = new _JsonStringifier(output, convert); |
| stringifier.stringifyValue(object); |
| return output.toString(); |
| } |
| - static void printOn(final object, StringSink output) { |
| - _JsonStringifier stringifier = new _JsonStringifier(output); |
| + static void printOn(final object, StringSink output, convert(object)) { |
| + _JsonStringifier stringifier = new _JsonStringifier(output, convert); |
| stringifier.stringifyValue(object); |
| } |
| @@ -695,11 +703,8 @@ class _JsonStringifier { |
| } |
| void checkCycle(final object) { |
| - // TODO: use Iterables. |
| - for (int i = 0; i < seen.length; i++) { |
| - if (identical(seen[i], object)) { |
| - throw new JsonCyclicError(object); |
| - } |
| + if (seen.contains(object)) { |
| + throw new JsonCyclicError(object); |
| } |
| seen.add(object); |
| } |
| @@ -711,11 +716,11 @@ class _JsonStringifier { |
| if (!stringifyJsonValue(object)) { |
| checkCycle(object); |
| try { |
| - var customJson = object.toJson(); |
| + var customJson = converter(object); |
| if (!stringifyJsonValue(customJson)) { |
| throw new JsonUnsupportedObjectError(object); |
| } |
| - seen.removeLast(); |
| + seen.remove(object); |
| } catch (e) { |
| throw new JsonUnsupportedObjectError(object, cause: e); |
| } |
| @@ -760,7 +765,7 @@ class _JsonStringifier { |
| } |
| } |
| sink.write(']'); |
| - seen.removeLast(); |
| + seen.remove(object); |
| return true; |
| } else if (object is Map) { |
| checkCycle(object); |
| @@ -779,7 +784,7 @@ class _JsonStringifier { |
| first = false; |
| }); |
| sink.write('}'); |
| - seen.removeLast(); |
| + seen.remove(object); |
| return true; |
| } else { |
| return false; |