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 c1d122e064bfc999e1d268fa0b3a91cd7172750b..439ae89b6ab0acd8a882fd07a421c53cb05e00de 100644 |
| --- a/pkg/serialization/lib/src/format.dart |
| +++ b/pkg/serialization/lib/src/format.dart |
| @@ -52,23 +52,22 @@ class SimpleMapFormat extends Format { |
| * This effectively defines a custom JSON serialization format, although |
| * the details of the format vary depending which rules were used. |
| */ |
| - String generateOutput(Writer w) { |
| + generateOutput(Writer w) { |
|
justinfagnani
2013/02/09 21:21:56
Style nit: Why remove the type here? Since the met
Jennifer Messerly
2013/02/10 00:20:35
Style nit nit :)
If return type is "dynamic", we
Alan Knight
2013/02/11 23:38:42
Good point, changed this to return Map<String, dyn
|
| var result = { |
| "rules" : w.serializedRules(), |
| "data" : w.states, |
| "roots" : w._rootReferences() |
| }; |
| - return json.stringify(result); |
| + return result; |
| } |
| /** |
| - * Read a [json] encoded string representing serialized data in this format |
| + * Read a [json] compatible representation of serialized data 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(String input, Reader reader) { |
| - var topLevel = json.parse(input); |
| + Map<String, dynamic> read(topLevel, Reader reader) { |
| var ruleString = topLevel["rules"]; |
| reader.readRules(ruleString); |
| return topLevel; |
| @@ -103,12 +102,20 @@ class SimpleJsonFormat extends Format { |
| SimpleJsonFormat({this.storeRoundTripInfo : false}); |
| /** |
| - * Generate output for this format from [w] and return it as a String which |
| - * is the [json] representation of a nested Map structure. |
| + * Generate output for this format from [w] and return it as |
| + * the [json] representation of a nested Map structure. |
| */ |
| - String generateOutput(Writer w) { |
| + generateOutput(Writer w) { |
|
justinfagnani
2013/02/09 21:21:56
Map as the return type?
Jennifer Messerly
2013/02/10 00:20:35
I don't think it necessarily returns a map if not
Alan Knight
2013/02/11 23:38:42
It doesn't necessarily return a Map, part of the c
|
| jsonify(w); |
| - return json.stringify(w.stateForReference(w._rootReferences().first)); |
| + var root = w._rootReferences().first; |
| + if (root is Reference) root = w.stateForReference(root); |
| + if (w.selfDescribing && storeRoundTripInfo) { |
| + root = { |
| + "rules" : w.serializedRules(), |
|
Jennifer Messerly
2013/02/08 04:04:38
I think I usually just indent this +2, since it ha
Alan Knight
2013/02/11 23:38:42
Because I made those be identifiers rather than li
|
| + "data" : root |
| + }; |
| + } |
| + return root; |
| } |
| /** |
| @@ -156,13 +163,18 @@ class SimpleJsonFormat extends Format { |
| * converted into Reference objects. Note that if the data was not written |
| * with [storeRoundTripInfo] true this will fail. |
| */ |
| - Map<String, dynamic> read(String input, Reader r) { |
| - var data = json.parse(input); |
| - var result = {}; |
| - result["rules"] = null; |
| - var ruleData = |
| - new List(r.serialization.rules.length).map((x) => []).toList(); |
| - var top = recursivelyFixUp(data, r, ruleData); |
| + Map<String, dynamic> read(data, Reader reader) { |
| + var result = new Map(); |
| + bool looksLikeItHasOurExtraData = data is Map && |
| + data.containsKey("rules") && data.containsKey("data"); |
| + var rules = looksLikeItHasOurExtraData ? data["rules"] : null; |
| + reader.readRules(rules); |
|
justinfagnani
2013/02/09 21:21:56
what happens here if "rules" is just some user dat
Jennifer Messerly
2013/02/10 00:20:35
This is a good idea.
We should go even further IM
Alan Knight
2013/02/11 23:38:42
OK, I changed this to just look at the "selfDescri
|
| + var ruleData = new List(reader.serialization.rules.length). |
| + map((x) => []).toList(); |
| + // If our result was a map with rules and data, get the data part. Otherwise |
| + // assume that the whole thing is the data. |
| + var actualData = (rules == null) ? data : data["data"]; |
| + var top = recursivelyFixUp(actualData, reader, ruleData); |
| result["data"] = ruleData; |
| result["roots"] = [top]; |
| return result; |
| @@ -171,20 +183,28 @@ class SimpleJsonFormat extends Format { |
| /** |
| * Convert nested references in [data] into [Reference] objects. |
| */ |
| - recursivelyFixUp(data, Reader r, List result) { |
| + recursivelyFixUp(input, Reader r, List result) { |
| + var data = input; |
| if (isPrimitive(data)) { |
| result[r._primitiveRule().number].add(data); |
| return data; |
| } |
| var ruleNumber; |
| + // If we've added the rule number on as the last item in a list we have |
| + // to get rid of it or it will be interpreted as extra data. For a map |
| + // the library will be ok, but we need to get rid of the extra key before |
| + // the data is shown to the user, so we destructively modify. |
| if (data is List) { |
| - ruleNumber = data.removeLast(); |
| + ruleNumber = data.last; |
| + data = data.take(data.length -1); |
| } else if (data is Map) { |
| ruleNumber = data.remove(ruleIdentifier); |
| } else { |
| throw new SerializationException("Invalid data format"); |
| } |
| - var newData = mapValues(data, (x) => recursivelyFixUp(x, r, result)); |
| + // Do not use mappedBy or other lazy operations for this. They do not play |
| + // well with a function that destructively modifies its arguments. |
| + var newData = mapValues(data, (each) => recursivelyFixUp(each, r, result)); |
| result[ruleNumber].add(newData); |
| return new Reference(r, ruleNumber, result[ruleNumber].length - 1); |
| } |