AdaptiveCards 在 .NET 解析期间引发异常

Posted

技术标签:

【中文标题】AdaptiveCards 在 .NET 解析期间引发异常【英文标题】:AdaptiveCards throws an exception during .NET parsing 【发布时间】:2021-11-14 05:25:55 【问题描述】:

我目前在解析自适应卡片时遇到了以下问题。

这是卡片:


    "type": "AdaptiveCard",
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.4",
    "body": [
        
            "type": "TextBlock",
            "text": "DATE($$root.AdditionalData['DUE-DATE'],COMPACT)",
            "wrap": true
        
    ]

这是卡片内容:


    "AdditionalData": 
      "DUE-DATE": "2021-09-10T16:29:59Z"
    

代码: c# on .NET Framework 4.7.2 其中layout 是带有上述卡片的字符串,content 是带有上述卡片内容的字符串:

 AdaptiveCardTemplate template = new AdaptiveCardTemplate(layout);
 string cardJson = template.Expand(content);

 AdaptiveCardParseResult card = AdaptiveCard.FromJson(cardJson);

它崩溃了:

AdaptiveCards.AdaptiveSerializationException: 'Error reading string. Unexpected token: Undefined. Path 'text', line 1, position 137.'
JsonReaderException: Error reading string. Unexpected token: Undefined. Path 'text', line 1, position 137.

cardJson 上生成的 JSON 在 text 属性中看起来不对:

"type":"AdaptiveCard","$schema":"http://adaptivecards.io/schemas/adaptive-card.json","version":"1.4","body":["type":"TextBlock","text":,"wrap":true]

我正在使用自适应卡 nuget 包:

AdaptiveCards 2.7.2 AdaptiveCards.Templating 1.2.

我是否遇到了解析错误? text 属性的值应为 10.9.2021。

在adaptivecards.io 的设计器中,出于某种原因,一切正常。有没有人有修复/解决方法?

【问题讨论】:

在 cardJson 上生成的 JSON 肯定是格式错误的。将其上传到jsonformatter.curiousconcept.com 或jsonlint.com,您将收到"text": , 缺少属性值的错误。所以问题不在于解析,而在于 JSON 生成。对于cardJson 中的"text" 的值,您期望得到什么?是"DATE(2021-09-10T16:29:59Z, COMPACT)"吗? @dbc 该值应为 10.9.2021。通常自适应卡片会在给定的上下文中呈现它。它适用于在线自适应卡片设计器 (adaptivecards.io),但不适用于 .Net 【参考方案1】:

如果您希望文字 "text":"10.9.2021" 出现在您的 cardJson 中,请使用 "$formatDateTime(AdditionalData['DUE-DATE'], 'd.M.yyyy')" 为您的 TextBlock 生成所需的值:


  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.4",
  "body": [
    
      "type": "TextBlock",
      "text": "$formatDateTime(AdditionalData['DUE-DATE'], 'd.M.yyyy')",
      "wrap": true
    
  ]

这会导致AdaptiveCardTemplate 执行所有日期格式并导致:


   "type":"AdaptiveCard",
   "$schema":"http://adaptivecards.io/schemas/adaptive-card.json",
   "version":"1.4",
   "body":[
      
         "type":"TextBlock",
         "text":"10.9.2021",
         "wrap":true
      
   ]

演示小提琴 #1 here.

如果您希望 "DATE(2021-09-10T16:29:59Z, COMPACT)"cardJson 中使用 delegates date formatting to the TextBlock,请使用:


  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.4",
  "body": [
    
      "type": "TextBlock",
      "text": "DATE($AdditionalData['DUE-DATE'], COMPACT)",
      "wrap": true
    
  ]

结果

      "text": "DATE(2021-09-10T16:29:59Z, COMPACT)",

演示小提琴 #2 here.

注意事项:

    根据Microsoft documentation:

    使用点符号 来访问对象层次结构的子对象。例如,$myParent.myChild 使用索引器语法通过键或数组中的项检索属性。例如,$myArray[0]

    但是,当访问名称中带有连字符(或其他一些reserved operator)的对象属性时,显然有必要使用索引器语法['DUE-DATE'] 而不是点符号来检索其值,传递属性将单引号字符串中的名称作为索引器。

    根据docs

    有一些保留关键字可以访问各种绑定范围。 ...

    "$root": "The root data object. Useful when iterating to escape to parent object",
    

    因此,当使用点表示法访问当前作用域对象(默认情况下为根)的属性时,您不需要使用$root。如果出于某种原因您需要或想要直接处理根对象,您可以使用$root,如下所示:

    "text": "$formatDateTime($root.AdditionalData['DUE-DATE'], 'd.M.yyyy')",
    

    演示小提琴#3 here.

    但是,似乎将$rootDATE() 结合使用会导致生成格式错误的JSON。即

      "text": "DATE($$root.AdditionalData['DUE-DATE'], COMPACT)",
    

    结果为@​​987654356@,如您的问题所示。

    演示小提琴#4 here.

    这看起来是框架中的一个错误。可能解析器阻塞了标记序列$$,因为您的问题有点类似于Issue #6026: [Authoring][.NET][Templating] Inconsistency in accessing $root inside a $when property in adaptive card templating,它报告无法正确解析"$when": "$$root.UserName != null"

    您可以通过完全省略$root 或将$root.AdditionalData['DUE-DATE'] 包装在额外的formatDateTime() 中来避免此问题,如下所示:

       "text": "DATE($formatDateTime($root.AdditionalData['DUE-DATE']), COMPACT)",
    

    导致

       "text": "DATE(2021-09-10T16:29:59.000Z, COMPACT)",
    

    演示小提琴 #5 here.

    来自文档页面Adaptive Card Templating SDKs: Troubleshooting:

    问。为什么 RFC 3389 格式的日期/时间(例如“2017-02-14T06:08:00Z”与模板一起使用时不适用于 TIME/DATE 函数? A. .NET sdk nuget 版本 1.0.0-rc.0 表现出这种行为。此行为在后续版本中得到纠正...请使用 formatDateTime() 函数将日期/时间字符串格式化为 RFC 3389,如 this example 中所示,或者您可以绕过 TIME/DATE 函数,而只使用 formatDateTime()。有关formatDateTime()的更多信息,请转至here。

    虽然使用 formatDateTime 的建议是为了解决 1.0.0-rc.0 中的问题,但该技巧也解决了上面注释 #2 中提到的问题。

【讨论】:

以上是关于AdaptiveCards 在 .NET 解析期间引发异常的主要内容,如果未能解决你的问题,请参考以下文章

在JSON.NET数据解析期间忽略解析错误

Microsoft Teams - 在聊天中呈现自适应卡片的问题

如何正确解析要在 ASP.NET Core 3.1 的 ConfigureServices() 中使用的服务?

microsoft botframework bot 如何在自适应卡片中提及用户?

为啥 Ajv 在编译期间无法解析引用?

为啥必须在 componentDidMount() 期间解析函数中的函数调用?