JSON Converter & Registry

1. Requirements Document

1.1 Overview

This library provides a compile-time generated JSON conversion registry that enables applications to convert raw JSON data into strongly typed objects using a centralized mechanism.

Instead of relying on conditional logic, reflection, or scattered factory calls, the solution introduces:

  • Explicit opt-in via annotations
  • Build-time discovery of eligible models
  • A generated registry mapping types to JSON factory functions
  • A single runtime entry point for decoding objects and lists

The design philosophy mirrors established dependency-injection patterns where registration is code-generated and initialization is explicitly invoked by the developer.

1.2 User Stories

  • US-1: As an application developer, I want to convert JSON into typed objects without writing repetitive parsing logic.
  • US-2: As a framework user, I want support for multiple model-generation strategies without changing runtime code.
  • US-3: As a plugin author, I want to decode models dynamically using their type.
  • US-4: As a maintainer, I want all supported models to be discoverable at compile time.
  • US-5: As a performance-conscious developer, I want zero reflection and predictable runtime behavior.

1.3 Functional Requirements

  1. Annotation-Driven: Developers must be able to mark models as eligible for JSON conversion using a package-specific annotation.
  2. Single Strategy: Exactly one conversion strategy must be declared per model.
  3. Registry Generation: The build system must scan annotated models and generate a registry file.
  4. Type Mapping: The generated registry must map runtime types to JSON factory functions.
  5. Initialization: The library must provide a standard initialization hook for registering generated factories.
  6. Runtime API: The runtime API must support:
    • Decoding a single object from a map
    • Decoding a list of objects from an iterable
    • Type-safe generic decoding
  7. Result-Based Results: The system must provide structured success and failure results.

1.4 Non-Functional Requirements

  • No runtime reflection
  • Compatible with Flutter and pure Dart environments
  • Deterministic build output
  • Minimal runtime overhead
  • Clear error messages for misconfiguration
  • Safe handling of invalid or unexpected JSON shapes

1.5 Constraints & Assumptions

  • Only explicitly annotated models participate in conversion
  • Code generation is mandatory
  • Initialization must be performed exactly once
  • JSON input is assumed to be decoded into map / list structures prior to usage

2. Technical Document

2.1 Architecture

System Architecture

The workflow is split into two phases: specific factory discovery at Build Time and generic type resolution at Runtime. The Generated Registry acts as the bridge, ensuring no reflection is required.

2.2 API Design

Annotation & Strategy Declaration

class KConvert {
  final KConvertType type;
  const KConvert({required this.type});
}
 
enum KConvertType { jsonSerializable, freezed, custom }
@JsonSerializable()
@KConvert(type: KConvertType.jsonSerializable)
class MyClass {
   // ...
}

Generated Registry (Example Output)

// Generated Code - Do not modify
typedef JsonFactory<T> = T Function(Map<String, dynamic> json);
 
const Map<Type, JsonFactory> factories = {
  StorageBox: StorageBox.fromJson,
  AppConfig: AppConfig.fromJson,
};

Initialization Contract

@KConvertInit
void registerConverters() async =>
    await KConverter.instance.register(factories);

Runtime Decoding API

class JsonTypeParser {
  static KResult<T> decodeMap<T>(Map<String, dynamic> values) {
    // generic lookup logic
  }
 
  static KResult<List<T>> decodeList<T>(Iterable values) {
    // generic list lookup logic
  }
}

2.3 Failure Model

The runtime decoding API follows a result-based error model rather than throwing unchecked exceptions. All decode operations return a KResult<T> wrapper.

Failure Categories:

  • RegistryNotInitialized: Init hook was never called.
  • TypeNotRegistered: Requested T is not in the map.
  • InvalidStructure: JSON shape doesn't match expectations.
  • FactoryFailure: The fromJson method itself threw an error.