Chromium Code Reviews| Index: pkg/serialization/lib/src/format.dart |
| diff --git a/pkg/serialization/lib/src/format.dart b/pkg/serialization/lib/src/format.dart |
| index e45a7f0c323f9007945b6e32a8558651b1dd18b1..13a6cbe685231605133f29520468801e9b94b6c1 100644 |
| --- a/pkg/serialization/lib/src/format.dart |
| +++ b/pkg/serialization/lib/src/format.dart |
| @@ -36,26 +36,21 @@ abstract class Format { |
| } |
| /** |
| - * A format that stores the data in maps which are converted into a JSON |
| - * string. Note that the maps aren't nested, and it handles cyclic references |
| - * by converting object references to [Reference] objects. If you want simple |
| - * acyclic JSON look at [SimpleJsonFormat]. |
| + * This is the most basic format, which provides the internal representation |
| + * of the serialization, exposing the Reference objects. |
| */ |
| -class SimpleMapFormat extends Format { |
| - |
| - const SimpleMapFormat(); |
| +class InternalMapFormat extends Format { |
| + const InternalMapFormat(); |
| /** |
| - * Generate output for this format from [w] and return it as a String which |
| - * is the [json] representation of a nested Map structure. The top level has |
| + * Generate output for this format from [w] and return it as a nested Map |
| + * structure. The top level has |
| * 3 fields, "rules" which may hold a definition of the rules used, |
| * "data" which holds the serialized data, and "roots", which holds |
| * [Reference] objects indicating the root objects. Note that roots are |
| - * necessary because the data is organized in the same way as the object |
| + * necessary because the data is not organized in the same way as the object |
| * structure, it's a list of lists holding self-contained maps which only |
| * refer to other parts via [Reference] objects. |
| - * This effectively defines a custom JSON serialization format, although |
| - * the details of the format vary depending which rules were used. |
| */ |
| Map<String, dynamic> generateOutput(Writer w) { |
| var result = { |
| @@ -67,7 +62,7 @@ class SimpleMapFormat extends Format { |
| } |
| /** |
| - * Read a [json] compatible representation of serialized data in this format |
| + * Read serialized data written from this format |
| * and return the nested Map representation described in [generateOutput]. If |
| * the data also includes rule definitions, then these will replace the rules |
| * in the [Serialization] for [reader]. |
| @@ -75,6 +70,94 @@ class SimpleMapFormat extends Format { |
| Map<String, dynamic> read(topLevel, Reader reader) { |
| var ruleString = topLevel["rules"]; |
| reader.readRules(ruleString); |
| + reader._data = topLevel["data"]; |
| + topLevel["roots"] = topLevel["roots"]; |
| + return topLevel; |
| + } |
| +} |
| + |
| + |
| +/** |
| + * A format that stores the data in maps which can be converted into a JSON |
| + * string or passed through an isolate. Note that this consists of maps, but |
| + * that they don't follow the original object structure or look like the nested |
| + * maps of a [json] representation. They are flat, and [Reference] objects |
| + * are converted into a map form that will not make sense to |
| + * anything but this format. For simple acyclic JSON that other programs |
| + * can read, use [SimpleJsonFormat]. This is the default format, and is |
| + * easier to read than the more efficient [SimpleFlatFormat]. |
| + */ |
| +class SimpleMapFormat extends InternalMapFormat { |
| + |
| + const SimpleMapFormat(); |
| + |
| + /** |
| + * Generate output for this format from [w] and return it as a String which |
| + * is the [json] representation of a nested Map structure. The top level has |
| + * 3 fields, "rules" which may hold a definition of the rules used, |
| + * "data" which holds the serialized data, and "roots", which holds |
| + * [Reference] objects indicating the root objects. Note that roots are |
| + * necessary because the data is not organized in the same way as the object |
| + * structure, it's a list of lists holding self-contained maps which only |
| + * refer to other parts via [Reference] objects. |
| + * This effectively defines a custom JSON serialization format, although |
| + * the details of the format vary depending which rules were used. |
| + */ |
| + Map<String, dynamic> generateOutput(Writer w) { |
| + forAllStates(w, (x) => x is Reference, referenceToMap); |
| + var result = super.generateOutput(w); |
| + result["roots"] = result["roots"].map( |
| + (x) => x is Reference ? referenceToMap(x) : x).toList(); |
| + return result; |
| + } |
| + |
| + /** |
| + * Convert the data generated by the rules to have maps with the fields |
| + * of [Reference] objects instead of the [Reference] so that the structure |
| + * can be serialized between isolates and json easily. |
| + */ |
| + forAllStates(ReaderOrWriter w, Function predicate, Function transform) { |
|
Jennifer Messerly
2013/05/14 00:21:39
more precise types for the function args?
e.g.
|
| + for (var eachRule in w.rules) { |
| + var ruleData = w.states[eachRule.number]; |
| + for (var data in ruleData) { |
| + keysAndValues(data).forEach((key, value) { |
| + if (predicate(value)) { |
|
Jennifer Messerly
2013/05/14 00:21:39
-2 indent here. Since it's a function, usually is
|
| + data[key] = transform(value); |
| + } |
| + }); |
| + } |
| + } |
| + } |
| + |
| + /** Convert the reference to a [json] serializable form. */ |
| + Map<String, int> referenceToMap(Reference ref) => ref == null ? null : |
| + { |
| + "__Ref" : 0, |
| + "rule" : ref.ruleNumber, |
| + "object" : ref.objectNumber |
| + }; |
| + |
| + /** |
| + * Convert the [referenceToMap] form for a reference back to a [Reference] |
| + * object. |
| + */ |
| + Reference mapToReference(ReaderOrWriter parent, Map<String, int> ref) => |
| + ref == null ? null : new Reference(parent, ref["rule"], ref["object"]); |
| + |
| + /** |
| + * Read serialized data written in this format |
| + * and return the nested Map representation described in [generateOutput]. If |
| + * the data also includes rule definitions, then these will replace the rules |
| + * in the [Serialization] for [reader]. |
| + */ |
| + Map<String, dynamic> read(topLevel, Reader reader) { |
| + super.read(topLevel, reader); |
| + forAllStates(reader, |
| + (ref) => ref is Map && ref["__Ref"] != null, |
| + (ref) => mapToReference(reader, ref)); |
| + topLevel["roots"] = topLevel["roots"] |
| + .map((x) => x is Map<String, int> ? mapToReference(reader, x) : x) |
| + .toList(); |
| return topLevel; |
| } |
| } |
| @@ -90,7 +173,7 @@ class SimpleMapFormat extends Format { |
| * If the [storeRoundTripInfo] field of the format is set to true, then this |
| * will store the rule number along with the data, allowing reconstruction. |
| */ |
| -class SimpleJsonFormat extends Format { |
| +class SimpleJsonFormat extends SimpleMapFormat { |
| /** |
| * Indicate if we should store rule numbers with map/list data so that we |