Send a adaptive card with data in python using 1.2 version

Question:

Based on the below, I have a card template and data separately as json.

https://adaptivecards.io/samples/FlightItinerary.html

But i am not sure how to send data through python for the below card. I cant find a documentation examples for template and data for python.
How do I send data to this card through python

    # code for adaptive card
    reply = MessageFactory.list([])
    reply.attachment_layout = AttachmentLayoutTypes.carousel
    reply.attachments.append(CardFactory.adaptive_card(LIST_JOB_CARD_CONTENT))
    await step_context.context.send_activity(reply)
LIST_JOB_CARD_CONTENT ={
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Job Number",
"size": "Small",
"weight": "Bolder",
"color": "Accent"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Job Status",
"fontType": "Default",
"size": "Small",
"color": "Accent",
"weight": "Bolder",
"horizontalAlignment": "Center"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Design Reference",
"weight": "Bolder",
"color": "Accent",
"size": "Small",
"horizontalAlignment": "Right"
}
]
}
],
"style": "default",
"spacing": "Small",
"horizontalAlignment": "Center",
"height": "stretch",
"minHeight": "5px"
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "${$root.JobNumber}",
"size": "Medium",
"color": "Good",
"weight": "Bolder"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "${$root.jobStatus}",
"weight": "Bolder",
"color": "Attention",
"size": "Medium",
"horizontalAlignment": "Center"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "${$root.DesignReference}",
"size": "Medium",
"weight": "Bolder",
"color": "Good",
"horizontalAlignment": "Center"
}
]
}
],
"style": "default",
"spacing": "Small",
"horizontalAlignment": "Center",
"height": "stretch"
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "250px",
"items": [
{
"type": "TextBlock",
"text": "Customer Name",
"size": "Medium",
"weight": "Bolder",
"color": "Accent",
"horizontalAlignment": "Center",
"spacing": "Medium"
}
],
"backgroundImage": {
"horizontalAlignment": "Center"
},
"spacing": "Small"
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Promotion",
"horizontalAlignment": "Center",
"size": "Medium",
"weight": "Bolder",
"color": "Accent"
}
]
}
],
"id": "CustomerName"
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "250px",
"items": [
{
"type": "TextBlock",
"horizontalAlignment": "Center",
"text": "${$root.CustomerName}",
"wrap": True,
"size": "Medium",
"fontType": "Monospace",
"color": "Good",
"weight": "Lighter"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "${$root.Promotion}",
"horizontalAlignment": "Center",
"fontType": "Monospace",
"size": "Medium",
"color": "Good"
}
]
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "50px",
"items": [
{
"type": "TextBlock",
"text": "Brand->",
"size": "Small",
"weight": "Bolder",
"color": "Accent"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "${$root.Brand}",
"id": "brand",
"wrap": True,
"size": "Medium",
"color": "Warning",
"horizontalAlignment": "Right"
}
]
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "100px",
"items": [
{
"type": "TextBlock",
"text": "RangeName->",
"fontType": "Default",
"size": "Small",
"weight": "Bolder",
"color": "Accent"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "${$root.RangeName}",
"size": "Medium",
"color": "Warning",
"horizontalAlignment": "Right"
}
]
}
]
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "60px",
"items": [
{
"type": "TextBlock",
"text": "Variety->",
"size": "Small",
"weight": "Bolder",
"color": "Accent"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "${$root.Variety}",
"horizontalAlignment": "Right",
"size": "Medium",
"color": "Warning"
}
]
}
]
}
]
}



  [1]: https://i.stack.imgur.com/YkjO4.png
Asked By: dhanush-ai1990

||

Answers:

Create your adaptive card in a json file (ie FlightItenerary.json), then use something like the following:

import json
import os
import random

from botbuilder.core import ActivityHandler, TurnContext, CardFactory
from botbuilder.schema import ChannelAccount, Attachment, Activity, ActivityTypes

CARDS = [
    "resources/FlightItineraryCard.json"
]


class AdaptiveCardsBot(ActivityHandler):

    async def on_message_activity(self, turn_context: TurnContext):
        message = Activity(
            text="Here is an Adaptive Card:",
            type=ActivityTypes.message,
            attachments=[self._create_adaptive_card_attachment()],
        )

        await turn_context.send_activity(message)

    def _create_adaptive_card_attachment(self) -> Attachment:
        card_path = os.path.join(os.getcwd(), CARDS[0])
        with open(card_path, "rb") as in_file:
            card_data = json.load(in_file)

        return CardFactory.adaptive_card(card_data)

This is altered code from the official bot framework sample 07. Using Adaptive Cards

Answered By: JJ_Wailes

I couldn’t find any way to pass in data to the JSON template using the Python SDK. However, I was able to solve this problem doing the following:

  1. In your .json file add tags (${key_name}) wherever you want to add a value passed in from python:
{
    "text": "${name}"
}
  1. Create a function that receives a dict (parsed json) and a dict with the key_name,value pairs you want to insert in the .json file:
def replace(template: dict, data:dict):
        import re
        str_temp = str(template)
        for key in data:
            pattern = "${"+key+"}"
            str_temp = re.sub(pattern, str(data[key]),str_temp)        
        return eval(str_temp)

  1. Use the function to replace all tags in the .json file:
def create_adaptive_card_attachment(self):
        # read the .json file
        relative_path = os.path.abspath(os.path.dirname(__file__))
        path = os.path.join(relative_path, "../cards/my_card.json")
        with open(path) as in_file:
            card_template = json.load(in_file)
        template_data = {"name":"Obi-Wan"}
        card =replace(card_template,template_data)
        
        return Attachment(
            content_type="application/vnd.microsoft.card.adaptive", content=card
        )
  1. Send the card to the user:
card = self.create_adaptive_card_attachment()
            response = MessageFactory.attachment(card)
            await step_context.context.send_activity(response)

Answered By: Pedro L
def replace(template: dict, data:dict):
        import re
        str_temp = json.dumps(template)
        for key in data:
            pattern = "${"+key+"}"
            str_temp = re.sub(pattern, str(data[key]),str_temp)        
        return json.loads(str_temp)

I suggest using Dharman’s answer, but please be mindful of using eval! This can be dangerous if you let your templated JSON depend on some form of user input. The function above solves this by first dumping the template into a JSON string (instead of doing a string() conversion yourself) and then properly re-converting it into a JSON object later with json.loads.

Answered By: Zenulous