# FromJson Desk > Turn a JSON payload a Flutter or Dart app receives into a null-safe dart:convert model with > fromJson and toJson, and check a hand-written model against the payload. The JSON reader, the > model generator and the checker run free in the browser; the review and the write are metered > model runs whose output the page runs through the same checker again. Live app: https://fromjson-desk.skillsafe.ai/ API tutorial: https://fromjson-desk.skillsafe.ai/api.html Derived from the agent skill @flutter/flutter-implement-json-serialization (flutter/skills, now flutter/agent-plugins, BSD-3-Clause): https://skillsafe.ai/skill/@flutter/flutter-implement-json-serialization/ ## What the browser does (free, no account) - Reads the payload with its own JSON parser so the int/double distinction survives: as with Dart's jsonDecode, 12 is an int, 12.0 and 1e3 are doubles, and an integer too large for 64 bits is a double. JSON.parse cannot tell these apart. - Accepts one object, a JSON list of objects (each element is a sample) or newline-delimited JSON (one object per line), and merges every sample into one schema: each key's JSON kinds, how many samples have it, how many are null, and example values. - Chooses Dart types: int; double (read as num and converted with toDouble when the JSON holds whole numbers, decimals or both); String; bool; DateTime for strings that DateTime.parse accepts and that carry a time (optional); a nested class per object; List per array; Object? when only null was seen or the kinds are mixed. A key missing from any sample is nullable. - Names the classes (root class from you, nested classes from their keys, list elements singularised) and the fields (lowerCamelCase, reserved words and names that would shadow Object members or core types renamed). - Generates the model in the skill's Dart 3 style (a switch over a map pattern with a FormatException fallback) or in cast style (json['key'] as T). Keys missing in some samples are read outside the map pattern, because a map pattern fails on an absent key even when its type is nullable, and are written back only when present. The generated code for many random payloads was compiled with Dart 3.13.4 and decoded its own samples. - Checks a pasted model: finds each class, its fields, its fromJson and its toJson, extracts the runtime check Dart applies to each key (an as cast, a map-pattern type, the parameter type of an untyped read, DateTime.parse, a nested fromJson, list element conversions, cast()), and runs it against every sample. It reports which samples throw and why, keys read but never present (with a did-you-mean), keys present but never read, keys read by fromJson but not written by toJson, and DateTime fields that jsonEncode cannot encode. Number checks follow the platform you choose: on the Dart VM as int throws on 12.0 and as double throws on 12; on the web (dart2js) numbers are JavaScript doubles and whole values pass both. - Exports the generated model (.dart), the schema (CSV), the check (Markdown) and the findings (CSV). The checker is not a Dart compiler. What it does not follow (reads through other expressions, list patterns, object patterns, when guards, generated json_serializable code) it reports as not checked. Its per-sample verdicts were compared with the real Dart VM and dart2js on generated and hand-written models with randomly broken payloads. ## The paid lanes (one system prompt, routed on the task field) - review: the payload, the schema, the checker's flags and your model go to the model, which answers every error and warning with what happens at runtime and the corrected Dart. Its verdict (decodes, fix_first, rewrite) may be stricter than the browser's floor, never looser. Each fix is checked against the samples; a fix that contains whole classes is run through the checker. - write: the schema, the generated skeleton and your options go to the model, which writes the model file, optionally a fetch function (package:http, status check, compute() for large payloads) and a unit test. The written model is run through the checker against every sample. Input: {"task": "review" | "write", "facts": "", "question": "optional"}. Model: gpt-terra. Runs are metered; the estimate is free. ## Sources - Dart jsonDecode: https://api.dart.dev/dart-convert/jsonDecode.html - Dart patterns: https://dart.dev/language/patterns - Numbers on the web: https://dart.dev/resources/language/number-representation - DateTime.parse: https://api.dart.dev/dart-core/DateTime/parse.html - Flutter JSON serialization guide: https://docs.flutter.dev/data-and-backend/serialization/json - Parsing in the background with compute: https://docs.flutter.dev/cookbook/networking/background-parsing - Source skill: https://github.com/flutter/agent-plugins/tree/main/skills/flutter-implement-json-serialization