| 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..93a345b1b92da128c355c4f85e89c2067177654e 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, bool predicate(value),
|
| + void transform(value)) {
|
| + 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)) {
|
| + 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
|
|
|