Skip to content

[XrmQuery 7] Request serializer strips outer braces from any {…}-wrapped string value, corrupting JSON stored in text columns #320

Open

Description

@Kristoffer88

Describe the bug

The request serializer strips the outer braces off any string value that starts with { and ends with }, assuming it is a brace-wrapped GUID. transformObject in src/XrmQuery/src/body.ts:

if (typeof obj === "string" && obj.startsWith("{") && obj.endsWith("}")) {
  return obj.substring(1, obj.length - 1);
}

Any JSON document, JSON-ish text, or template string stored in a Dataverse text/memo column via create/update is silently corrupted: {"version":2} arrives at the server as "version":2, which is no longer parseable. We hit this in production code that persists a JSON config document to a memo column — the write succeeds, and the corruption only surfaces when the document is read back and JSON.parse fails (or, worse, a fallback silently discards the stored state).

To Reproduce

// npm i @delegateas/xrmquery@7.0.0-preview.3 && node repro.mjs
import { XrmQuery, configure } from "@delegateas/xrmquery";

let sentBody;
configure({
  baseUrl: "https://org.crm4.dynamics.com/api/data/v9.2/",
  fetch: async (_url, init) => {
    sentBody = init.body;
    return new Response(null, { status: 204 });
  },
});

const document = JSON.stringify({ version: 2, lanes: ["a", "b"] });
await XrmQuery.update((x) => x.accounts, "00000000-0000-0000-0000-000000000001", {
  description: document,
}).execute();

console.log(JSON.parse(sentBody).description);

Output with 7.0.0-preview.3:

"version":2,"lanes":["a","b"]

Also verified against a live org (Web API v9.2): the value stored in the column is the brace-stripped string.

Expected behavior

String values are sent verbatim. Only values that are actually brace-wrapped GUIDs (/^\{[0-9A-Fa-f]{8}(-[0-9A-Fa-f]{4}){3}-[0-9A-Fa-f]{12}\}$/) should be unwrapped — or better, brace-stripping could be limited to the places where a GUID is expected (_bind$/_id$ values and id parameters) instead of applying to every string in the payload.

Notes

This is faithfully ported legacy behaviour — v6's dg.xrmquery.web.ts has the identical check in its transformObject — so it's not a preview regression. But since the serializer is being rewritten anyway, preview seems like the right time to fix the default.

Environment

  • @delegateas/xrmquery 7.0.0-preview.3 (npm)
  • Reproduces in Node 24 and the browser; confirmed against Dataverse online, Web API v9.2

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions