| Index: sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart
|
| diff --git a/sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart b/sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..d67cd72e2bc5287e7328b30afb752bec34855908
|
| --- /dev/null
|
| +++ b/sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart
|
| @@ -0,0 +1,238 @@
|
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +/**
|
| + * Simple library to serialize acyclic Dart types to JSON.
|
| + * This library is not intended for broad consumption and should be replaced
|
| + * with a more generic Dart serialization library when one is available.
|
| + */
|
| +library json_serializer;
|
| +
|
| +import 'dart:mirrors';
|
| +import 'dart:json';
|
| +
|
| +String serialize(Object o) {
|
| + var printer = new JsonPrinter();
|
| + _serialize(null, o, printer);
|
| + return printer.toString();
|
| +}
|
| +
|
| +void _serialize(String name, Object o, JsonPrinter printer) {
|
| + if (o == null) return;
|
| +
|
| + if (o is List) {
|
| + _serializeList(name, o, printer);
|
| + } else if (o is Map) {
|
| + _serializeMap(name, o, printer);
|
| + } else if (o is String) {
|
| + printer.addString(name, o);
|
| + } else if (o is bool) {
|
| + printer.addBool(name, o);
|
| + } else {
|
| + _serializeObject(name, o, printer);
|
| + }
|
| +}
|
| +
|
| +void _serializeObject(String name, Object o, JsonPrinter printer) {
|
| + printer.startObject(name);
|
| +
|
| + var mirror = reflect(o);
|
| + var classMirror = mirror.type;
|
| + var members = <String>[];
|
| + determineAllMembers(classMirror, members);
|
| +
|
| + // TODO(jacobr): this code works only because futures for mirrors return
|
| + // immediately.
|
| + for(String memberName in members) {
|
| + mirror.getField(memberName).then((result) {
|
| + _serialize(memberName, result.reflectee, printer);
|
| + });
|
| + }
|
| + printer.endObject();
|
| +}
|
| +
|
| +void determineAllMembers(ClassMirror classMirror,
|
| + List<String> members) {
|
| + for(String getterName in classMirror.getters.keys) {
|
| + if (!members.contains(getterName)) {
|
| + members.add(getterName);
|
| + }
|
| + }
|
| + for(String fieldName in classMirror.variables.keys) {
|
| + if (!members.contains(fieldName)) {
|
| + members.add(fieldName);
|
| + }
|
| + }
|
| + if (classMirror.superclass != null &&
|
| + classMirror.superclass.qualifiedName != classMirror.qualifiedName &&
|
| + classMirror.superclass.qualifiedName != 'dart:core.Object') {
|
| + determineAllMembers(classMirror.superclass, members);
|
| + }
|
| +}
|
| +
|
| +void _serializeList(String name, List l, JsonPrinter printer) {
|
| + printer.startList(name);
|
| + for(var o in l) {
|
| + _serialize(null, o, printer);
|
| + }
|
| + printer.endList();
|
| +}
|
| +
|
| +void _serializeMap(String name, Map m, JsonPrinter printer) {
|
| +}
|
| +
|
| +class JsonPrinter {
|
| + static const int BACKSPACE = 8;
|
| + static const int TAB = 9;
|
| + static const int NEW_LINE = 10;
|
| + static const int FORM_FEED = 12;
|
| + static const int CARRIAGE_RETURN = 13;
|
| + static const int QUOTE = 34;
|
| + static const int BACKSLASH = 92;
|
| + static const int CHAR_B = 98;
|
| + static const int CHAR_F = 102;
|
| + static const int CHAR_N = 110;
|
| + static const int CHAR_R = 114;
|
| + static const int CHAR_T = 116;
|
| + static const int CHAR_U = 117;
|
| +
|
| + StringBuffer _sb;
|
| + int _indent = 0;
|
| + bool _inSet = false;
|
| +
|
| + bool _prettyPrint;
|
| + JsonPrinter({this._prettyPrint: true}) {
|
| + _sb = new StringBuffer();
|
| + }
|
| +
|
| + void startObject(String name) {
|
| + _start(name);
|
| + _sb.add('{');
|
| +
|
| + _indent += 1;
|
| + _inSet = false;
|
| + }
|
| +
|
| + void endObject() {
|
| + _indent -= 1;
|
| + if (_inSet) {
|
| + _newline();
|
| + }
|
| + _sb.add('}');
|
| + _inSet = true;
|
| + }
|
| +
|
| + void startList(String name) {
|
| + _start(name);
|
| + _inSet = false;
|
| +
|
| + _sb.add('[');
|
| + _indent += 1;
|
| + }
|
| +
|
| + void endList() {
|
| + _indent -= 1;
|
| + if (_inSet) {
|
| + _newline();
|
| + }
|
| + _sb.add(']');
|
| + _inSet = true;
|
| + }
|
| +
|
| + void addString(String name, String value) {
|
| + _start(name);
|
| + _sb.add('"');
|
| + _escape(_sb, value);
|
| + _sb.add('"');
|
| + _inSet = true;
|
| + }
|
| +
|
| + void addBool(String name, bool value) {
|
| + _start(name);
|
| + _sb.add(value.toString());
|
| + _inSet = true;
|
| + }
|
| +
|
| + void addNum(String name, num value) {
|
| + _start(name);
|
| + _sb.add(value.toString());
|
| + _inSet = true;
|
| + }
|
| +
|
| + void _start(String name) {
|
| + if (_inSet) {
|
| + _sb.add(',');
|
| + }
|
| + _newline();
|
| + if (name != null) {
|
| + _sb.add('"$name": ');
|
| + }
|
| + }
|
| +
|
| + void _newline([int indent = 0]) {
|
| + _sb.add('\n');
|
| + _indent += indent;
|
| +
|
| + for (var i = 0; i < _indent; ++i) {
|
| + _sb.add(' ');
|
| + }
|
| + }
|
| +
|
| + String toString() {
|
| + if (_prettyPrint) {
|
| + return _sb.toString();
|
| + } else {
|
| + // Convenient hack to remove the pretty printing this serializer adds by
|
| + // default.
|
| + return JSON.stringify(JSON.parse(_sb.toString()));
|
| + }
|
| + }
|
| +
|
| + static int _hexDigit(int x) => x < 10 ? 48 + x : 87 + x;
|
| +
|
| + static void _escape(StringBuffer sb, String s) {
|
| + final int length = s.length;
|
| + bool needsEscape = false;
|
| + final charCodes = new List<int>();
|
| + for (int i = 0; i < length; i++) {
|
| + int charCode = s.charCodeAt(i);
|
| + if (charCode < 32) {
|
| + needsEscape = true;
|
| + charCodes.add(JsonPrinter.BACKSLASH);
|
| + switch (charCode) {
|
| + case JsonPrinter.BACKSPACE:
|
| + charCodes.add(JsonPrinter.CHAR_B);
|
| + break;
|
| + case JsonPrinter.TAB:
|
| + charCodes.add(JsonPrinter.CHAR_T);
|
| + break;
|
| + case JsonPrinter.NEW_LINE:
|
| + charCodes.add(JsonPrinter.CHAR_N);
|
| + break;
|
| + case JsonPrinter.FORM_FEED:
|
| + charCodes.add(JsonPrinter.CHAR_F);
|
| + break;
|
| + case JsonPrinter.CARRIAGE_RETURN:
|
| + charCodes.add(JsonPrinter.CHAR_R);
|
| + break;
|
| + default:
|
| + charCodes.add(JsonPrinter.CHAR_U);
|
| + charCodes.add(_hexDigit((charCode >> 12) & 0xf));
|
| + charCodes.add(_hexDigit((charCode >> 8) & 0xf));
|
| + charCodes.add(_hexDigit((charCode >> 4) & 0xf));
|
| + charCodes.add(_hexDigit(charCode & 0xf));
|
| + break;
|
| + }
|
| + } else if (charCode == JsonPrinter.QUOTE ||
|
| + charCode == JsonPrinter.BACKSLASH) {
|
| + needsEscape = true;
|
| + charCodes.add(JsonPrinter.BACKSLASH);
|
| + charCodes.add(charCode);
|
| + } else {
|
| + charCodes.add(charCode);
|
| + }
|
| + }
|
| + sb.add(needsEscape ? new String.fromCharCodes(charCodes) : s);
|
| + }
|
| +}
|
|
|