带有 Cosmos DB 绑定的 Azure 函数返回格式化的日期时间?
Azure Function with Cosmos DB binding returning formatted DateTime?
我 运行 在 CosmosDB 中存储作为字符串给出的 DateTime 对象时遇到了一些困难。为了确保它与 DateTime 对象的序列化无关,我目前只使用 strings.
我在数据库中存储的文档如下所示:
{
"available": true,
"id": "391a802c-ac42-443b-860a-8ab7061b389c",
"checked_date": "2020-06-04T12:53:29.4625341Z",
"code": "AAAA",
"_rid": "w6VGAOSKaJABAAAAAAAAAA==",
"_self": "dbs/w6VGAA==/colls/w6VGAOSKaJA=/docs/w6VGAOSKaJABAAAAAAAAAA==/",
"_etag": "\"00000000-0000-0000-3a70-96abc3ea01d6\"",
"_attachments": "attachments/",
"_ts": 1591275829
}
我正在使用一个非常简单的函数来查询它:
[FunctionName("GetObject")]
public static async Task<IActionResult> GetObject(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "object/{code}")] HttpRequest req,
[CosmosDB(
databaseName: "database01",
collectionName: "objecttable",
ConnectionStringSetting = "CosmosDBString",
SqlQuery = "SELECT c.id, c.code, c.available, c.checked_date FROM objecttable c WHERE LOWER(c.code)=LOWER({code})")] IEnumerable<ObjectEntity> entities,
ILogger log)
{
log.LogInformation("GetObject function processed a request.");
return new JsonResult(entities);
}
ObjectEntity class 看起来像这样:
[JsonObject(MemberSerialization.OptIn)]
public class ObjectEntity
{
[JsonProperty(PropertyName = "available")]
public bool Available {get; set;}
[JsonProperty(PropertyName = "id")]
public string Id {get; set;}
[JsonProperty(PropertyName = "checked_date")]
public string CheckedDate {get; set;}
[JsonProperty(PropertyName = "code")]
public string Code{get; set;}
}
当在字段 "checked_date" 中存储一些任意字符串数据时,字符串只是按预期 returned。当我存储像“2020-06-04T12:53:29.4625341Z”这样的字符串时,我得到的是“06/04/2020 12:53:29”returned——没有应用任何反序列化、类型转换或类似的东西。
使用 CosmosDB Explorer,我看到了正确的字符串表示形式。
这与 Azure 函数的 return 对象无关,问题已经在函数中发生。如果我在函数中设置一个断点,我可以看到实体对象中的字符串已经搞砸了。
我在这里做错了什么? CosmosDB 绑定是否弄乱了我的字符串?
更新:
我已将 CosmosDB 连接模式设置为 "Direct" 并使用 Fiddler 跟踪请求。似乎 CosmosDB 确实 return 响应正文中的正确字符串:
{"_rid":"w6VGAOSKaJA=","Documents":[{"id":"391a802c-ac42-443b-860a-8ab7061b389c","code":"AAAA","available":true,"checked_date":"2020-06-04T12:53:29.4625341Z"}],"_count":1}
所以问题必须与绑定本身或反序列化有关?
这可能与 SDK 使用默认 Newtonsoft.Json 序列化程序设置有关,该设置将字符串解析为日期时间 (https://github.com/Azure/azure-cosmos-dotnet-v2/issues/235 and https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_DateParseHandling.htm),DateParseHandling.None
将解决它。
遗憾的是,绑定不允许您定义 DocumentClient
的初始化方式。一种替代方法是维护您自己的实例,而不是使用绑定(我猜最后会有更多代码)。 DocumentClient
有一个构造函数,让您指定 JsonSerializerSettings
.
的实例
确保实例是在 Functions' guidelines.
之后创建的
另一种选择是全局设置它,但这会影响所有其他使用 Newtonsoft.Json 的代码:Json.net global settings
最后,您可以在 属性 上创建一个自定义转换器,它只按原样输出文本。
我 运行 在 CosmosDB 中存储作为字符串给出的 DateTime 对象时遇到了一些困难。为了确保它与 DateTime 对象的序列化无关,我目前只使用 strings.
我在数据库中存储的文档如下所示:
{
"available": true,
"id": "391a802c-ac42-443b-860a-8ab7061b389c",
"checked_date": "2020-06-04T12:53:29.4625341Z",
"code": "AAAA",
"_rid": "w6VGAOSKaJABAAAAAAAAAA==",
"_self": "dbs/w6VGAA==/colls/w6VGAOSKaJA=/docs/w6VGAOSKaJABAAAAAAAAAA==/",
"_etag": "\"00000000-0000-0000-3a70-96abc3ea01d6\"",
"_attachments": "attachments/",
"_ts": 1591275829
}
我正在使用一个非常简单的函数来查询它:
[FunctionName("GetObject")]
public static async Task<IActionResult> GetObject(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "object/{code}")] HttpRequest req,
[CosmosDB(
databaseName: "database01",
collectionName: "objecttable",
ConnectionStringSetting = "CosmosDBString",
SqlQuery = "SELECT c.id, c.code, c.available, c.checked_date FROM objecttable c WHERE LOWER(c.code)=LOWER({code})")] IEnumerable<ObjectEntity> entities,
ILogger log)
{
log.LogInformation("GetObject function processed a request.");
return new JsonResult(entities);
}
ObjectEntity class 看起来像这样:
[JsonObject(MemberSerialization.OptIn)]
public class ObjectEntity
{
[JsonProperty(PropertyName = "available")]
public bool Available {get; set;}
[JsonProperty(PropertyName = "id")]
public string Id {get; set;}
[JsonProperty(PropertyName = "checked_date")]
public string CheckedDate {get; set;}
[JsonProperty(PropertyName = "code")]
public string Code{get; set;}
}
当在字段 "checked_date" 中存储一些任意字符串数据时,字符串只是按预期 returned。当我存储像“2020-06-04T12:53:29.4625341Z”这样的字符串时,我得到的是“06/04/2020 12:53:29”returned——没有应用任何反序列化、类型转换或类似的东西。
使用 CosmosDB Explorer,我看到了正确的字符串表示形式。
这与 Azure 函数的 return 对象无关,问题已经在函数中发生。如果我在函数中设置一个断点,我可以看到实体对象中的字符串已经搞砸了。
我在这里做错了什么? CosmosDB 绑定是否弄乱了我的字符串?
更新: 我已将 CosmosDB 连接模式设置为 "Direct" 并使用 Fiddler 跟踪请求。似乎 CosmosDB 确实 return 响应正文中的正确字符串:
{"_rid":"w6VGAOSKaJA=","Documents":[{"id":"391a802c-ac42-443b-860a-8ab7061b389c","code":"AAAA","available":true,"checked_date":"2020-06-04T12:53:29.4625341Z"}],"_count":1}
所以问题必须与绑定本身或反序列化有关?
这可能与 SDK 使用默认 Newtonsoft.Json 序列化程序设置有关,该设置将字符串解析为日期时间 (https://github.com/Azure/azure-cosmos-dotnet-v2/issues/235 and https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_DateParseHandling.htm),DateParseHandling.None
将解决它。
遗憾的是,绑定不允许您定义 DocumentClient
的初始化方式。一种替代方法是维护您自己的实例,而不是使用绑定(我猜最后会有更多代码)。 DocumentClient
有一个构造函数,让您指定 JsonSerializerSettings
.
确保实例是在 Functions' guidelines.
之后创建的另一种选择是全局设置它,但这会影响所有其他使用 Newtonsoft.Json 的代码:Json.net global settings
最后,您可以在 属性 上创建一个自定义转换器,它只按原样输出文本。