Long time ago we decided to use XSuperObject
library for marshalling objects into json for transition between two parts of system. One of fields represents as ISuperObject
on server side and as various object on client side.
The idea is that I send objects to server and then it returns one of this back without any changes. For example I send this:
[
{
"NAME": "Today",
"VALUE": {"loginIndex": 0,"shipmentDate": "2023-09-08","shipmentAddressId": "","paymentMethodId": "","shipmentMethodId": "","shipmentOfficeId": ""},
"IS_DEFAULT": false,
"ID": 0,
"WH_ID": 0
},
{
"NAME": "Monday",
"VALUE": {"loginIndex": 0,"shipmentDate": "2023-09-11","shipmentAddressId": "","paymentMethodId": "","shipmentMethodId": "","shipmentOfficeId": ""},
"IS_DEFAULT": false,
"ID": 0,
"WH_ID": 0
},
{
"NAME": "Tuesday",
"VALUE": {"loginIndex": 0,"shipmentDate": "2023-09-12","shipmentAddressId": "","paymentMethodId": "","shipmentMethodId": "","shipmentOfficeId": ""},
"IS_DEFAULT": false,
"ID": 0,
"WH_ID": 0
}
]
and translate into object with this structure:
TMySelectedItem = record
NAME:String;
VALUE:ISuperObject;
IS_DEFAULT:Boolean;
ID:Integer;
WH_ID:Integer;
end
When I translate JSON to object using TSuperRecord<TMySelectedItem>.FromJSON(Resp.Data[i])
, extract VALUE field and translate it into string using VALUE.AsJSON
, I expect this:
{"loginIndex": 0,"shipmentDate": "2023-09-08","shipmentAddressId": "","paymentMethodId": "","shipmentMethodId": "","shipmentOfficeId": ""}
but instead, server returns me this:
{"loginIndex": 0,"shipmentDate": "2023-09-07Z","shipmentAddressId": "","paymentMethodId": "","shipmentMethodId": "","shipmentOfficeId": ""}
As you can see, it not only recognize field shipmentDate
as date, as I suppose, it also changes timezone despite lack of time value in this string and especially I didn't tell it, that this field is a date. Can I mark field, typed ISuperObject to translate into output json as is, without any changes?
The library you use (XSuperObject) has built-in recognition of date, time and date-time values from JSON string values when reading JSON. This is enabled by default.
Some of the APIs in the library gives you control over this behavior -
TSuperObject.Create(JSON: String = '{}'; const CheckDate: Boolean = True)
, but this is not the case ofTSuperRecord<T>.FromJson(const JSON: String)
.In such a case you could use the version of
FromJson
method that takesISuperObject
as an argument that has date recognition explicitly disabled:But this won't work either due to bugs in the library:
CheckDate
parameter is not propagated to nested objects. MethodTBaseJSON<T, Typ>.GetObject(V: Typ): ISuperObject
returns new instance ofTSuperObject
withCheckDate
enabled by default.ISuperObject
insideTSuperRecord<T>.FromJSON()
also ignores the value ofCheckDate
parameter that was used to createTSuperObject
instance. See methodTSuperObject.Clone: ISuperObject
Those are just two bugs that apply to your scenario, but I guess there's more, because the library lacks test suite. In theory you could ask the author to fix those bugs, or contribute bug fixes, but based on issues and commits the project seems pretty much dead to me.
The library contains static class
TJSONDateManager
that is responsible for recognizing dates. It containsFormats
class property which is initialized with ISO-8601 format. Clearing these formats will disable any date recognition and the solution to your specific problem will become one-liner:At this point you depend on the library that is buggy and you probably won't get any support. I strongly recommend you to switch to some other library.
FWIW, the proposed fixes to bugs mentioned above are: