From 8b2c540741f71cdf2e89aa07a72707282de9e90f Mon Sep 17 00:00:00 2001 From: andig Date: Mon, 22 Jun 2026 12:52:33 +0200 Subject: [PATCH] Issue report: sort template key first in config dump (#31079) --- assets/js/components/Issue/format.test.ts | 20 ++++++++++++++++++++ assets/js/components/Issue/format.ts | 20 ++++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/assets/js/components/Issue/format.test.ts b/assets/js/components/Issue/format.test.ts index bb237927f..54ae08bad 100644 --- a/assets/js/components/Issue/format.test.ts +++ b/assets/js/components/Issue/format.test.ts @@ -107,6 +107,26 @@ describe("formatJson", () => { {"baz":123,"foo":"bar"}, {"id":1,"num":456,"qux":"test"} ] +}`); + }); + + it("sorts template first inside nested config of array items", () => { + const obj = { + charger: [ + { + config: { host: "192.168.1.1", template: "tesla" }, + name: "db:1", + type: "template", + id: 1, + }, + ], + }; + const result = formatJson(obj, ["charger"]); + + expect(result).toBe(`{ + "charger": [ + {"id":1,"name":"db:1","type":"template","config":{"template":"tesla","host":"192.168.1.1"}} + ] }`); }); }); diff --git a/assets/js/components/Issue/format.ts b/assets/js/components/Issue/format.ts index fdf168ab3..bfe1c3c21 100644 --- a/assets/js/components/Issue/format.ts +++ b/assets/js/components/Issue/format.ts @@ -10,6 +10,17 @@ function sortedEntries(obj: object): [string, any][] { }); } +// recursively reorder keys so priority keys (e.g. template) stay first at every nesting level +function sortedDeep(value: any): any { + if (Array.isArray(value)) { + return value.map(sortedDeep); + } + if (value && typeof value === "object") { + return Object.fromEntries(sortedEntries(value).map(([k, v]) => [k, sortedDeep(v)])); + } + return value; +} + export function formatJson(obj: any, expandKeys: string[] = []): string { if (!obj || typeof obj !== "object") { return JSON.stringify(obj, null, 2); @@ -31,10 +42,7 @@ export function formatJson(obj: any, expandKeys: string[] = []): string { valueStr = "[]"; } else { const arrayItems = value.map((item) => { - const itemStr = - item && typeof item === "object" && !Array.isArray(item) - ? JSON.stringify(Object.fromEntries(sortedEntries(item))) - : JSON.stringify(item); + const itemStr = JSON.stringify(sortedDeep(item)); return ` ${itemStr.replace(/\\n/g, "\n")}`; }); valueStr = `[\n${arrayItems.join(",\n")}\n ]`; @@ -47,7 +55,7 @@ export function formatJson(obj: any, expandKeys: string[] = []): string { valueStr = "{}"; } else { const objItems = objEntries.map(([k, v]) => { - const itemStr = JSON.stringify(v); + const itemStr = JSON.stringify(sortedDeep(v)); return ` ${JSON.stringify(k)}: ${itemStr.replace(/\\n/g, "\n")}`; }); valueStr = `{\n${objItems.join(",\n")}\n }`; @@ -55,7 +63,7 @@ export function formatJson(obj: any, expandKeys: string[] = []): string { } } else { // Single line for everything else - valueStr = JSON.stringify(value).replace(/\\n/g, "\n"); + valueStr = JSON.stringify(sortedDeep(value)).replace(/\\n/g, "\n"); } lines.push(` ${JSON.stringify(key)}: ${valueStr}`);