Reputation: 169
I'm using Azure APIM policy expression to aggregate multiple responses. In that one of the JSON response contains multiple dateTime fields. all of them are in UTC TZ. I want to deserialize all of the date fields to specific Timezone(in my case SGT +08:00) from +00:00
Input:
{
"Header": {
"UserID": "xxxxxx",
"MessageID": "xxxxxx",
"CorrelationID": "xxxx",
"DateTime": "2018-02-12T15:31:18+00:00",
"ReqID": "xxx"
},
"ResultSet": {
"Tier": {
"CardSuffix": "91",
"RetentionDeadline": "2022-02-27T16:00:00+00:00",
"PointsRequireToQualify": "xxxxx",
"QualifyingDeadline": "2022-02-27T16:00:00+00:00",
"SignupDate": "2020-08-07",
"IssuedDate": "2021-06-15",
"JoiningDateTime": "2010-03-31T10:10:00+00:00",
"RequireToUpgradeInYear": "288886",
"YearlyUpgradeDeadline": "2022-02-27T16:00:00+00:00",
"CurrentCardDesc": "xxxxxxxx",
"NextCardDesc": "xxxxxxxxx",
"CurrentTierPoints": "0",
"UpdatedDateTime": "2023-01-09T17:43:54.844+00:00",
"LastRefreshedDateTime": "2022-02-10T07:45:13+00:00"
}
}
}
Expected Output:
{
"Header": {
"UserID": "xxxxxx",
"MessageID": "xxxxxx",
"CorrelationID": "xxxx",
"DateTime": "2018-02-12T15:31:18+08:00",
"ReqID": "xxx"
},
"ResultSet": {
"Tier": {
"CardSuffix": "91",
"RetentionDeadline": "2022-02-28T0:00:00+08:00",
"PointsRequireToQualify": "xxxxx",
"QualifyingDeadline": "2022-02-28T0:00:00+08:00",
"SignupDate": "2020-08-07",
"IssuedDate": "2021-06-15",
"JoiningDateTime": "2010-03-31T10:10:00+08:00",
"RequireToUpgradeInYear": "288886",
"YearlyUpgradeDeadline": "2022-02-28T0:00:00+08:00",
"CurrentCardDesc": "xxxxxxxx",
"NextCardDesc": "xxxxxxxxx",
"CurrentTierPoints": "0",
"UpdatedDateTime": "2023-01-10T22:08:08+08:00",
"LastRefreshedDateTime": "2022-02-10T15:45:13+08:00"
}
}
}
I have tried and achieved the expected output by using ConvertTimeBySystemTimeZoneId(DateTimeOffset, String) Method, But real Problem is I don't want to add each individual Property name to change the time zone with Offset. I need generic efficient solution that deserialize DateTime fields to Specific TimeZone with the format .ToString("yyyy-MM-ddTH:mm::sszzz")
Here's my fiddle: sample
If you see my above sample, I have parse the input as JObject and converts to required format for the first property alone
obj["ResultSet"]["Tier"]["RetentionDeadline"]
which changed from "RetentionDeadline": "2022-02-27T16:00:00+00:00",
to "RetentionDeadline": "2022-02-28T0:00:00+08:00",
Problem with this solution: If any new DateField is added in the backend response, I need to revisit my policy expression again and do this manual conversion. So I want generic one time conversion for all dateTime fields.
Please note that I'm writing this inside policy expression; so I can't reuse the functionality by using any c# extensions or helper methods.
Upvotes: 1
Views: 352
Reputation: 169
Update: My backend has been sending proper TimeZone data.
If your response has a Proper DateTime field with TimeZone and you want to keep the original value in TimeZone, this DateParseHandling = DateParseHandling.None
can be used.
Below is an example Snippet.
https://dotnetfiddle.net/AlPJmk
This could be useful to someone.
Upvotes: 0
Reputation: 3967
You can do this by looping over the children of the JSON object:
var obj = context.Request.Body.AsJObject(true, new JsonSerializerSettings() { DateParseHandling = DateParseHandling.None } );
foreach (JProperty x in (JToken)obj["ResultSet"]["Tier"])
{}
DateParseHandling is used for the date format does not change.
A very simple Regex is used to recognize dates 2022-02-27T
:
^[0-9]{4}-[0-9]{2}-[0-9]{2}T
Complete policy:
<policies>
<inbound>
<base />
<return-response>
<set-status code="200" reason="OK" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>@{
var obj = context.Request.Body.AsJObject(true, new JsonSerializerSettings() { DateParseHandling = DateParseHandling.None } );
var pattern = @"^[0-9]{4}-[0-9]{2}-[0-9]{2}T";
var regex = new Regex(pattern);
foreach (JProperty x in (JToken)obj["ResultSet"]["Tier"])
{
string name = x.Name;
JToken tokenValue = x.Value;
if(regex.IsMatch(tokenValue.ToString()))
{
obj["ResultSet"]["Tier"][name] = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(new DateTimeOffset(Convert.ToDateTime(obj["ResultSet"]["Tier"][name])), "Singapore Standard Time").ToString("yyyy-MM-ddTH:mm::sszzz");
}
}
return obj.ToString();
}</set-body>
</return-response>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
Result:
Upvotes: 2