OData default serializers: Edm.TimeOfDay rejects seconds in (59, 60), Edm.Decimal loses fractional digits or uses exponential notation

Aperta
#7,067 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
65/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
typescript
Ambito
api

Direzione di ricerca

Start with the three named spots: validateTime in packages/odata-v4/src/de-serializers/converters.ts (the seconds check), the Edm.Decimal branch in packages/odata-v4/src/de-serializers/default-de-serializers.ts, and serializeFromBigNumber in packages/odata-common/src/de-serializers/payload-value-converter.ts. Run the repro script from the issue to see the current output. Done means the three expected values in the issue are returned and the existing odata-v4 and odata-v2 serializer tests still pass.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Describe the Bug

There are three serialization bugs in the default OData de-serializers:

  1. OData v4 Edm.TimeOfDay rejects fractional seconds in (59, 60): deserializeToTime('23:59:59.5') returns { hours: 23, minutes: 59, seconds: 59.5 }, but passing that object back to serializeToTime throws Provided time value [object Object] can not be serialized to a valid Edm.TimeOfDay. Any entity read from a service whose Edm.TimeOfDay falls in the last second of a minute with fractional seconds cannot be serialized back in a request payload, key, or filter.
  2. OData v4 Edm.Decimal silently truncates fractional digits to IEEE-754 double precision: defaultDeSerializers['Edm.Decimal'].serialize converts the BigNumber with value.toNumber() and returns the number whenever it lies between Number.MIN_SAFE_INTEGER and Number.MAX_SAFE_INTEGER. That bounds check only protects large integers; a decimal with more than ~16 significant digits (such as '1234567.123456789012') is inside the safe-integer range and loses its trailing digits (1234567.123456789) in both payloads and URIs.
  3. OData v2 and v4 Edm.Decimal format small and large numbers in exponential notation: serializeFromBigNumber calls value.toString(), which switches to exponential notation at <= 1e-7 and >= 1e+21. For example, '0.00000001' serializes in v2 as '1e-8' in payloads and '1e-8M' in URIs (which is not a valid OData v2 decimal literal), and '1000000000000000000000' serializes as '1e+21' in both v2 and v4.
Steps to Reproduce
  1. Install @sap-cloud-sdk/[email protected] and @sap-cloud-sdk/[email protected].
  2. Run node repro.js with the script in Code Examples below.
Expected Behavior
  1. v4['Edm.TimeOfDay'].serialize(v4['Edm.TimeOfDay'].deserialize('23:59:59.5')) returns '23:59:59.5'.
  2. v4['Edm.Decimal'].serialize(v4['Edm.Decimal'].deserialize('1234567.123456789012')) preserves all digits ('1234567.123456789012').
  3. Edm.Decimal serialization produces plain decimal strings without exponential notation ('0.00000001', '0.00000001M', '1000000000000000000000').
Screenshots

No response

Used Versions
  • Node version via node -v: v26.13.0 (also reproduced on v24.22.2)
  • NPM version via npm -v: 11.20.0
  • SAP Cloud SDK version: @sap-cloud-sdk/[email protected], @sap-cloud-sdk/[email protected] (and main at 76cfd545)
  • For CAP users, CAP version: N/A
Code Examples
const { defaultDeSerializers: v4 } = require('@sap-cloud-sdk/odata-v4');
const { defaultDeSerializers: v2 } = require('@sap-cloud-sdk/odata-v2');

// 1. v4 Edm.TimeOfDay with seconds in (59, 60)
const tod = v4['Edm.TimeOfDay'];
console.log(tod.serialize(tod.deserialize('10:15:58.999'))); // '10:15:58.999'
try {
  console.log(tod.serialize(tod.deserialize('23:59:59.5')));
} catch (e) {
  console.log(e.message);
  // Provided time value [object Object] can not be serialized to a valid Edm.TimeOfDay
}

// 2. v4 Edm.Decimal precision loss
const dec4 = v4['Edm.Decimal'];
console.log(dec4.serialize(dec4.deserialize('1234567.123456789012'))); // 1234567.123456789
console.log(dec4.serialize(dec4.deserialize('0.1234567890123456789'))); // 0.12345678901234568
console.log(dec4.serializeToUri(dec4.deserialize('1234567.123456789012'), dec4.serialize)); // '1234567.123456789'

// 3. v2 / v4 Edm.Decimal exponential notation
const dec2 = v2['Edm.Decimal'];
console.log(dec2.serialize(dec2.deserialize('0.00000001'))); // '1e-8'
console.log(dec2.serializeToUri(dec2.deserialize('0.00000001'), dec2.serialize)); // '1e-8M'
console.log(dec2.serialize(dec2.deserialize('1000000000000000000000'))); // '1e+21'
console.log(dec4.serialize(dec4.deserialize('1000000000000000000000'))); // '1e+21'
Log File
Error: Provided time value [object Object] can not be serialized to a valid Edm.TimeOfDay
Affected Development Phase

Development

Impact

Impaired

Timeline

No response

Additional Context
  • In packages/odata-v4/src/de-serializers/converters.ts, validateTime checks seconds > 59; because fractional seconds are stored in seconds as a float, this should be seconds >= 60.
  • In packages/odata-v4/src/de-serializers/default-de-serializers.ts, Edm.Decimal only checks MIN_SAFE_INTEGER <= primitiveNumber <= MAX_SAFE_INTEGER before returning value.toNumber(), which does not check whether new BigNumber(primitiveNumber).isEqualTo(value).
  • In packages/odata-common/src/de-serializers/payload-value-converter.ts, serializeFromBigNumber calls value.toString() instead of value.toFixed().

Credit: https://ucsbplse.github.io/

Lingua principale
TypeScript
Stelle
221
Fork
79
Merge medio
13h 27m
PR unite (30g)
22

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di SAP/cloud-sdk-js

Tutte le issue di SAP/cloud-sdk-js

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.