Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
2352599
Change OData store default value of deserializeDates
GoodDayForSurf Nov 5, 2025
c4d1399
Change OData store default value of deserializeDates + fix deprecated
GoodDayForSurf Nov 6, 2025
b6c34a0
Change OData store default value of deserializeDates + fix deprecated
GoodDayForSurf Nov 6, 2025
0b81d43
Merge branch '25_2' of https://github.com/DevExpress/DevExtreme into …
GoodDayForSurf Nov 6, 2025
2ba223c
Change OData store default value of deserializeDates + fix serializeV…
GoodDayForSurf Nov 6, 2025
87cf02b
Change OData store default value of deserializeDates + rename option
GoodDayForSurf Nov 6, 2025
3a67ab6
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 6, 2025
dd9701b
Merge remote-tracking branch 'my/25_2_odata_deserialize_dates' into 2…
GoodDayForSurf Nov 6, 2025
cc9b5a9
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 7, 2025
a272046
Change OData store default value of deserializeDates
GoodDayForSurf Nov 7, 2025
9796b40
Merge branch '25_2_odata_deserialize_dates' of https://github.com/Goo…
GoodDayForSurf Nov 7, 2025
7a1c33f
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 7, 2025
eb93a4c
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 7, 2025
7c323b8
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 7, 2025
41e61a1
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 10, 2025
3313c30
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 10, 2025
70e210c
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 10, 2025
3c510bc
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 10, 2025
3b580ed
Change OData store default
GoodDayForSurf Nov 10, 2025
c36d137
Merge branch '25_2_odata_deserialize_dates' of https://github.com/Goo…
GoodDayForSurf Nov 10, 2025
d20ab74
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 10, 2025
19bb242
Change OData store default
GoodDayForSurf Nov 10, 2025
2273d25
Merge branch '25_2_odata_deserialize_dates' of https://github.com/Goo…
GoodDayForSurf Nov 10, 2025
cf5f119
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 11, 2025
a9130f4
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 11, 2025
c26d9c7
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 11, 2025
075624b
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 11, 2025
1473cd7
Change OData store default
GoodDayForSurf Nov 11, 2025
2ceaab7
Merge branch '25_2_odata_deserialize_dates' of https://github.com/Goo…
GoodDayForSurf Nov 11, 2025
dde943c
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 11, 2025
ad83b9b
Merge branch '25_2_odata_deserialize_dates' of https://github.com/Goo…
GoodDayForSurf Nov 11, 2025
b489736
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 11, 2025
886cdac
Change OData store default
GoodDayForSurf Nov 11, 2025
ecd1387
Change OData store default
GoodDayForSurf Nov 11, 2025
bfd1c5f
Merge remote-tracking branch 'my/25_2_odata_deserialize_dates' into 2…
GoodDayForSurf Nov 11, 2025
4d2117d
Change OData store default
GoodDayForSurf Nov 11, 2025
b464646
Change OData store default
GoodDayForSurf Nov 11, 2025
2142aa8
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 12, 2025
71ec5cc
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 12, 2025
0fb0c02
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 12, 2025
96f0c10
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 12, 2025
aa24a78
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 12, 2025
b92b22d
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 12, 2025
cc7cc4e
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 12, 2025
3a78410
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 13, 2025
ea8b697
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 13, 2025
dcc9b28
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 13, 2025
25d176f
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 14, 2025
2fdddc3
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 14, 2025
b0a4a33
Merge branch '25_2' into 25_2_odata_deserialize_dates
GoodDayForSurf Nov 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export class AppComponent implements AfterViewInit {
version: 2,
url: 'https://js.devexpress.com/Demos/DevAV/odata/Tasks',
key: 'Task_ID',
processDatesAsUtc: true,
},
expand: 'ResponsibleEmployee',
select: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const dataSource = {
version: 2,
url: 'https://js.devexpress.com/Demos/DevAV/odata/Tasks',
key: 'Task_ID',
processDatesAsUtc: true,
},
expand: 'ResponsibleEmployee',
select: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const dataSource = {
version: 2,
url: 'https://js.devexpress.com/Demos/DevAV/odata/Tasks',
key: 'Task_ID',
processDatesAsUtc: true,
},
expand: 'ResponsibleEmployee',
select: [
Expand Down
1 change: 1 addition & 0 deletions apps/demos/Demos/DataGrid/DeferredSelection/Vue/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ const dataSource: DataSourceOptions = {
version: 2,
url: 'https://js.devexpress.com/Demos/DevAV/odata/Tasks',
key: 'Task_ID',
processDatesAsUtc: true,
},
expand: 'ResponsibleEmployee',
select: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ $(() => {
version: 2,
url: 'https://js.devexpress.com/Demos/DevAV/odata/Tasks',
key: 'Task_ID',
processDatesAsUtc: true,
},
expand: 'ResponsibleEmployee',
select: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ const compileCriteria = (() => {

return formatter(
serializePropName(fieldName),
serializeValue(value, protocolVersion),
serializeValue(value, protocolVersion, fieldTypes?.[fieldName]),
);
};

Expand Down Expand Up @@ -277,7 +277,7 @@ const createODataQueryAdapter = (queryOptions) => {
jsonp: queryOptions.jsonp,
withCredentials: queryOptions.withCredentials,
countOnly: _countQuery,
deserializeDates: queryOptions.deserializeDates,
processDatesAsUtc: queryOptions.processDatesAsUtc,
fieldTypes: queryOptions.fieldTypes,
isPaged: isFinite(_take),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default class RequestDispatcher {
// @ts-expect-error
this._withCredentials = options.withCredentials;
// @ts-expect-error
this._deserializeDates = options.deserializeDates;
this._processDatesAsUtc = options.processDatesAsUtc ?? options.deserializeDates ?? false;
// @ts-expect-error
this._filterToLower = options.filterToLower;
}
Expand All @@ -40,7 +40,7 @@ export default class RequestDispatcher {
// @ts-expect-error
withCredentials: this._withCredentials,
// @ts-expect-error
deserializeDates: this._deserializeDates,
processDatesAsUtc: this._processDatesAsUtc,
},
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/devextreme/js/__internal/data/odata/m_store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ const ODataStore = Store.inherit({
withCredentials: this._requestDispatcher._withCredentials,
expand: loadOptions?.expand,
requireTotalCount: loadOptions?.requireTotalCount,
deserializeDates: this._requestDispatcher._deserializeDates,
processDatesAsUtc: this._requestDispatcher._processDatesAsUtc,
fieldTypes: this._fieldTypes,
};

Expand Down
29 changes: 18 additions & 11 deletions packages/devextreme/js/__internal/data/odata/m_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,15 @@ const ajaxOptionsForRequest = (protocolVersion, request, options = {}) => {

export const sendRequest = (protocolVersion, request, options) => {
const {
deserializeDates, fieldTypes, countOnly, isPaged,
processDatesAsUtc, fieldTypes, countOnly, isPaged,
} = options;
// @ts-expect-error
const d = new Deferred();
const ajaxOptions = ajaxOptionsForRequest(protocolVersion, request, options);

ajax.sendRequest(ajaxOptions).always((obj, textStatus) => {
const transformOptions = {
deserializeDates,
processDatesAsUtc,
fieldTypes,
};
const tuple = interpretJsonFormat(obj, textStatus, transformOptions, ajaxOptions);
Expand Down Expand Up @@ -387,14 +387,14 @@ const transformTypes = (obj, options = {}) => {
transformTypes(obj[key], options);
} else if (typeof value === 'string') {
// @ts-expect-error
const { fieldTypes, deserializeDates } = options;
const { fieldTypes, processDatesAsUtc } = options;
const canBeGuid = !fieldTypes || fieldTypes[key] !== 'String';

if (canBeGuid && GUID_REGEX.test(value)) {
obj[key] = new Guid(value);
}

if (deserializeDates !== false) {
if (processDatesAsUtc !== false) {
if (VERBOSE_DATE_REGEX.exec(value)) {
// @ts-expect-error
const date = new Date(Number(RegExp.$1) + RegExp.$2 * 60 * 1000);
Expand All @@ -415,20 +415,20 @@ export const serializePropName = (propName) => (propName instanceof EdmLiteral
? propName.valueOf()
: propName.replace(/\./g, '/'));

const serializeValueV4 = (value) => {
const serializeValueV4 = (value, fieldType) => {
if (value instanceof Date) {
return formatISO8601(value, false, false);
}
if (value instanceof Guid) {
return value.valueOf();
}
if (Array.isArray(value)) {
return `[${value.map((item) => serializeValueV4(item)).join(',')}]`;
return `[${value.map((item) => serializeValueV4(item, fieldType)).join(',')}]`;
}
return serializeValueV2(value);
return serializeValueV2(value, fieldType);
};

const serializeValueV2 = (value) => {
const serializeValueV2 = (value, fieldType) => {
if (value instanceof Date) {
return serializeDate(value);
}
Expand All @@ -438,19 +438,22 @@ const serializeValueV2 = (value) => {
if (value instanceof EdmLiteral) {
return value.valueOf();
}
if (fieldType && ['Date', 'DateTimeOffset'].includes(fieldType)) {
return value;
}
if (typeof value === 'string') {
return serializeString(value);
}
return String(value);
};

export const serializeValue = (value, protocolVersion) => {
export const serializeValue = (value, protocolVersion, fieldType?) => {
switch (protocolVersion) {
case 2:
case 3:
return serializeValueV2(value);
return serializeValueV2(value, fieldType);
case 4:
return serializeValueV4(value);
return serializeValueV4(value, fieldType);
default: throw errors.Error('E4002');
}
};
Expand Down Expand Up @@ -480,6 +483,10 @@ export const keyConverters = {
Single: (value) => (value instanceof EdmLiteral ? value : new EdmLiteral(`${value}f`)),

Decimal: (value) => (value instanceof EdmLiteral ? value : new EdmLiteral(`${value}m`)),

DateTimeOffset: (value) => value,

Date: (value) => value,
};

export const convertPrimitiveValue = (type, value) => {
Expand Down
20 changes: 19 additions & 1 deletion packages/devextreme/js/common/data.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1130,8 +1130,16 @@ export type ODataContextOptions = {
/**
* @docid
* @public
* @default false
* @deprecated ODataContextOptions.processDatesAsUtc
*/
deserializeDates?: boolean;
/**
* @docid ODataContextOptions.processDatesAsUtc
* @public
* @default false
*/
processDatesAsUtc?: boolean;
/**
* @docid
* @public
Expand Down Expand Up @@ -1232,8 +1240,16 @@ export type ODataStoreOptions<
/**
* @docid
* @public
* @default false
* @deprecated ODataStoreOptions.processDatesAsUtc
*/
deserializeDates?: boolean;
/**
* @docid ODataStoreOptions.processDatesAsUtc
* @public
* @default false
*/
processDatesAsUtc?: boolean;
/**
* @docid
* @type_function_param1 e:Error
Expand All @@ -1247,7 +1263,9 @@ export type ODataStoreOptions<
* @default {}
* @public
*/
fieldTypes?: any;
fieldTypes?: {
[fieldName: string]: 'String' | 'Int32' | 'Int64' | 'Guid' | 'Boolean' | 'Single' | 'Decimal' | 'Date' | 'DateTimeOffset';
};
/**
* @docid
* @public
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -916,16 +916,27 @@ QUnit.test('Values are converted according to \'fieldTypes\' property', function
fieldTypes: {
id1: 'Int64',
name: 'String',
total: 'Decimal' // T566307
total: 'Decimal', // T566307
date: 'Date',
dateTime: 'DateTimeOffset'
}
})
.filter([['id1', '=', 123], 'and', ['id2', '=', 456], 'and', ['name', '=', 789], 'and', ['total', '=', null]])
.filter([
['id1', '=', 123], 'and',
['id2', '=', 456], 'and',
['name', '=', 789], 'and',
['total', '=', null], 'and',
['date', '=', '2025-11-11'], 'and',
['dateTime', '=', '2025-11-11T11:11:11.000Z'], 'and',
['dateText', '=', '2025-11-11'], 'and',
['dateTimeText', '=', '2025-11-11T11:11:11.000Z'],
])
.enumerate()
.fail(function() {
assert.ok(false, MUST_NOT_REACH_MESSAGE);
})
.done(function(r) {
assert.equal(r[0].data['$filter'], '(id1 eq 123L) and (id2 eq 456) and (name eq \'789\') and (total eq null)');
assert.equal(r[0].data['$filter'], '(id1 eq 123L) and (id2 eq 456) and (name eq \'789\') and (total eq null) and (date eq 2025-11-11) and (dateTime eq 2025-11-11T11:11:11.000Z) and (dateText eq \'2025-11-11\') and (dateTimeText eq \'2025-11-11T11:11:11.000Z\')');
})
.always(done);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1718,7 +1718,7 @@ QUnit.test('Dates, on updating', function(assert) {
});

QUnit.module('Deserialization', moduleConfig);
QUnit.test('Dates, disableable, ODataStore', function(assert) {
QUnit.test('Dates, default behaviour (processDatesAsUtc = false), ODataStore', function(assert) {
assert.expect(2);

const done = assert.async();
Expand All @@ -1733,7 +1733,7 @@ QUnit.test('Dates, disableable, ODataStore', function(assert) {
responseText: { dateProperty: '1945-05-09T14:25:12.1234567Z' }
});

const store = new ODataStore({ version: 4, url: 'odata.org', deserializeDates: false });
const store = new ODataStore({ version: 4, url: 'odata.org' });
const promises = [
store.load()
.done(function(r) {
Expand All @@ -1751,7 +1751,7 @@ QUnit.test('Dates, disableable, ODataStore', function(assert) {
.always(done);
});

QUnit.test('Dates, disableable, ODataContext', function(assert) {
QUnit.test('Dates, default behaviour (processDatesAsUtc = false) and fieldType of dateProperty is undefined, ODataContext', function(assert) {
assert.expect(4);

const done = assert.async();
Expand All @@ -1774,10 +1774,9 @@ QUnit.test('Dates, disableable, ODataContext', function(assert) {
const ctx = new ODataContext({
version: 4,
url: 'odata.org',
deserializeDates: false,
entities: {
'X': { name: 'name' },
'Y': { name: 'name', deserializeDates: true }
'Y': { name: 'name', processDatesAsUtc: true }
}
});

Expand Down Expand Up @@ -1808,6 +1807,63 @@ QUnit.test('Dates, disableable, ODataContext', function(assert) {
.always(done);
});

QUnit.test('Dates, processDatesAsUtc = true, ODataContext', function(assert) {
assert.expect(4);

const done = assert.async();

ajaxMock.setup({
url: 'odata.org/name',
responseText: { value: [{ dateProperty: '1945-05-09T14:25:12.1234567Z' }] }
});

ajaxMock.setup({
url: 'odata.org/function()',
responseText: { dateProperty: '1945-05-09T14:25:12.1234567Z' }
});

ajaxMock.setup({
url: 'odata.org/action',
responseText: { dateProperty: '1945-05-09T14:25:12.1234567Z' }
});

const ctx = new ODataContext({
version: 4,
url: 'odata.org',
processDatesAsUtc: true,
entities: {
'X': { name: 'name' },
'Y': { name: 'name' }
}
});

const promises = [
ctx.get('function')
.done(function(r) {
assert.ok(isDate(r.dateProperty));
}),

ctx.invoke('action')
.done(function(r) {
assert.ok(isDate(r.dateProperty));
}),

ctx.X.load()
.done(function(r) {
assert.ok(isDate(r[0].dateProperty));
}),

ctx.Y.load()
.done(function(r) {
assert.ok(isDate(r[0].dateProperty));
})
];

$.when.apply($, promises)
.fail(function() { assert.ok(false, MUST_NOT_REACH_MESSAGE); })
.always(done);
});

QUnit.module('JSONP support', moduleConfig);
QUnit.test('load()', function(assert) {
const done = assert.async();
Expand Down
Loading
Loading