【问题标题】:AdaptiveCards throws an exception during .NET parsingAdaptiveCards 在 .NET 解析期间引发异常
【发布时间】: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.comjsonlint.com,您将收到"text": , 缺少属性值的错误。所以问题不在于解析,而在于 JSON 生成。对于cardJson 中的"text" 的值,您期望得到什么?是"{{DATE(2021-09-10T16:29:59Z, COMPACT)}}"吗?
  • @dbc 该值应为 10.9.2021。通常自适应卡片会在给定的上下文中呈现它。它适用于在线自适应卡片设计器 (adaptivecards.io),但不适用于 .Net

标签: c# json .net adaptive-cards


【解决方案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.

注意事项:

  1. 根据Microsoft documentation

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

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

  2. 根据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.

    但是,似乎将$root{{DATE()}} 结合使用会导致生成格式错误的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.

  3. 来自文档页面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 中提到的问题。

【讨论】:

    猜你喜欢
    • 2015-08-04
    • 1970-01-01
    • 2020-09-18
    • 2021-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    相关资源
    最近更新 更多