- 
                Notifications
    You must be signed in to change notification settings 
- Fork 82
Description
After #2677, we can make this package have lazy json reading similar to what we already do in the link input.
Phase 1: Use a Code Generator for JSON Serialization
The current implementation contains manually written toJson() and fromJson() methods. This code is complex, brittle, and must be carefully maintained. A significant improvement would be to use a code generation package like json_serializable or json_syntax_generator to handle this boilerplate automatically.
This will help with correctness of the implementation and create an official schema.
The deserialization would still be eager.
Phase 2: Lazy Deserialization
To facilitate API evolution, we can adopt lazy serialization. Any fields removed will not crash the program if not read.
However, splitting the API into a reader and a builder makes writing tests cumbersome.
To combine the performance benefits of a lazy JSON view with good developer experience a shared abstract API can be introduced:
- 
RecordedUsages: A straightforward implementation using plain Dart objects (Map,List, etc.). This class serves as the primary data container, is used for building new recordings, and is ideal for writing tests. It also implicitly defines the interface that consumers will use.
- 
RecordedUsagesJsonView: The production-ready implementation for reading large files. It would implement theRecordedUsagesclass and usejson_syntax_generatorinternally to provide the high-performance, lazy-loading view.
A developer writing a test can construct a RecordedUsages object directly, without any builders or serialization, and pass it to their function which accepts the RecordedUsages type.
We cannot lazily deserialize everything, see for example:
- [record_use] Correctness: Support non-string map keys #2715 (keys of maps should be de-normalized eagerly to allow for efficient lookup)
Alternatives Considered to Phase 2.
Alternative A: Separate Builder and Reader Classes
A common pattern is to have a RecordingsBuilder class for creating the data and a separate RecordedUsages class for reading it.
- Pro:
- Clear Separation of Concerns: The roles of writing (mutable, builder) and reading (immutable, reader) are explicitly separated into different classes.
 
- Con:
- Poor Test Experience: This forces test authors into a cumbersome "build -> serialize -> deserialize" loop to create test inputs.
 
Alternative B: Single, Eagerly-Loaded Class (Phase 1 solution)
This is the simplest approach, where there is only one set of "plain old Dart objects" for everything. The entire JSON is parsed into these objects on load.
- Pro:
- Simplicity: Very easy to understand and implement. Writing tests is straightforward as you just create the objects.
 
- Con:
- Inflexible Schema Evolution: This is the primary disadvantage. Because the entire JSON is deserialized into a strict set of Dart objects at once, the format becomes brittle. Any change to the JSON schema (like adding, removing, or renaming a field) would likely break older clients, as the eager deserialization logic would fail. A lazy-loading approach is often more resilient to such changes. (There is a reason we did this for the build and link hook input and output. We should not do something different for the recorded uses, unless we have a real good reason.)
 
Metadata
Metadata
Assignees
Labels
Type
Projects
Status