From 315d9866026014fb26b58e316f9b34a0239085ed Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Mon, 20 Jul 2026 17:16:48 -0400 Subject: [PATCH] fix(dart): keep top-level fromJson/toJson names with --from-map (#1719) Co-Authored-By: gpt-5.6-sol via pi --- .../src/language/Dart/DartRenderer.ts | 4 +- test/languages.ts | 8 ++- test/unit/dart-method-names.test.ts | 68 +++++++++++++++++++ 3 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 test/unit/dart-method-names.test.ts diff --git a/packages/quicktype-core/src/language/Dart/DartRenderer.ts b/packages/quicktype-core/src/language/Dart/DartRenderer.ts index 8a46bd7577..1b0cd45684 100644 --- a/packages/quicktype-core/src/language/Dart/DartRenderer.ts +++ b/packages/quicktype-core/src/language/Dart/DartRenderer.ts @@ -117,12 +117,12 @@ export class DartRenderer extends ConvenienceRenderer { const encoder = new DependencyName( propertyNamingFunction, name.order, - (lookup) => `${lookup(name)}_${this.toJson}`, + (lookup) => `${lookup(name)}_toJson`, ); const decoder = new DependencyName( propertyNamingFunction, name.order, - (lookup) => `${lookup(name)}_${this.fromJson}`, + (lookup) => `${lookup(name)}_fromJson`, ); this._topLevelDependents.set(name, { encoder, decoder }); return [encoder, decoder]; diff --git a/test/languages.ts b/test/languages.ts index 6bcfd43611..0d214b119e 100644 --- a/test/languages.ts +++ b/test/languages.ts @@ -1628,8 +1628,12 @@ export const DartLanguage: Language = { skipMiscJSON: true, rendererOptions: {}, // The default is final-props=true; this keeps the mutable-property - // code path covered. - quickTestRendererOptions: [{ "final-props": "false" }], + // code path covered. The targeted from-map sample also verifies that + // the fixture driver can keep calling the top-level JSON string helpers. + quickTestRendererOptions: [ + { "final-props": "false" }, + ["simple-object.json", { "from-map": "true" }], + ], sourceFiles: ["src/language/Dart/index.ts"], }; diff --git a/test/unit/dart-method-names.test.ts b/test/unit/dart-method-names.test.ts new file mode 100644 index 0000000000..17ed1e35c9 --- /dev/null +++ b/test/unit/dart-method-names.test.ts @@ -0,0 +1,68 @@ +import { describe, expect, test } from "vitest"; + +import { + InputData, + type RendererOptions, + jsonInputForTargetLanguage, + quicktype, +} from "../../packages/quicktype-core/src/index.js"; + +async function renderDart( + rendererOptions: RendererOptions = {}, +): Promise { + const jsonInput = jsonInputForTargetLanguage("dart"); + await jsonInput.addSource({ + name: "Sensordata", + samples: ['{"sensor":"temp","data":[1,2,3]}'], + }); + + const inputData = new InputData(); + inputData.addInput(jsonInput); + + const result = await quicktype({ + inputData, + lang: "dart", + rendererOptions, + }); + return result.lines; +} + +describe("Dart JSON method names", () => { + test("from-map only renames class-level map methods", async () => { + const lines = await renderDart({ "from-map": "true" }); + + expect(lines).toContain( + "Sensordata sensordataFromJson(String str) => Sensordata.fromMap(json.decode(str));", + ); + expect(lines).toContain( + "String sensordataToJson(Sensordata data) => json.encode(data.toMap());", + ); + expect(lines).toContain( + " factory Sensordata.fromMap(Map json) => Sensordata(", + ); + expect(lines).toContain(" Map toMap() => {"); + expect(lines.some((line) => line.includes("sensordataFromMap"))).toBe( + false, + ); + expect(lines.some((line) => line.includes("sensordataToMap"))).toBe( + false, + ); + }); + + test("uses Json names at both levels by default", async () => { + const lines = await renderDart(); + + expect(lines).toContain( + "Sensordata sensordataFromJson(String str) => Sensordata.fromJson(json.decode(str));", + ); + expect(lines).toContain( + "String sensordataToJson(Sensordata data) => json.encode(data.toJson());", + ); + expect(lines).toContain( + " factory Sensordata.fromJson(Map json) => Sensordata(", + ); + expect(lines).toContain(" Map toJson() => {"); + expect(lines.some((line) => line.includes("fromMap"))).toBe(false); + expect(lines.some((line) => line.includes("toMap"))).toBe(false); + }); +});