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
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
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:
- In your
.json
file add tags (${key_name}
) wherever you want to add a value passed in from python:
{
"text": "${name}"
}
- 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)
- 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
)
- Send the card to the user:
card = self.create_adaptive_card_attachment()
response = MessageFactory.attachment(card)
await step_context.context.send_activity(response)
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.
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
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
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:
- In your
.json
file add tags (${key_name}
) wherever you want to add a value passed in from python:
{
"text": "${name}"
}
- 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)
- 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
)
- Send the card to the user:
card = self.create_adaptive_card_attachment()
response = MessageFactory.attachment(card)
await step_context.context.send_activity(response)
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.