Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este artigo mostra como criar um item de mapa Fabric e aplicar uma definição de mapa usando Python. Demonstra tanto padrões de ordem de operações suportados como inclui o tratamento básico de erros.
Para criar um mapa Fabric programaticamente, precisas de dois componentes:
-
Uma definição de mapa (
map.json) - Um item de mapa num espaço de trabalho Fabric
Dependendo do padrão que escolher, pode:
- Crie primeiro o item do mapa e atribua a definição mais tarde, ou
- Crie o item do mapa com a definição em linha num único pedido
Este artigo demonstra ambas as abordagens.
Tip
Na maioria dos cenários de automação, utilize-se a abordagem que cria o mapa com a sua definição em linha. Esta abordagem garante que o mapa está totalmente configurado na altura da criação e evita chamadas adicionais de API.
Observação
Este artigo foca-se na criação e configuração de mapas (plano de controlo). Deve já ter dados referenciados pelo mapa (como ficheiros GeoJSON ou ícones SVG) no OneLake ou noutra fonte de dados suportada.
Pré-requisitos
- Acesso a um espaço de trabalho Fabric
- Identidade de aplicação ou utilizador Microsoft Entra ID com permissões de espaço de trabalho
- Python 3.9 ou posterior
- Um token de acesso OAuth 2.0 para a API Fabric REST
Exemplo de definição de mapa (map.json)
O exemplo seguinte apresenta uma carga útil simplificada map.json que:
- Usa o mapa base padrão
- Lê dados GeoJSON de uma origem de dados lakehouse
- Renderiza os dados como uma camada vetorial
A map.json definição é uma configuração declarativa que descreve:
-
dataSources(por exemplo, recursos lakehouse ou eventhouse que fornecem dados) -
layerSources(os ficheiros, tabelas ou funções que definem os dados para cada camada) -
layerSettings(as definições de visualização para cada camada, como cores, ícones ou estilo)
A definição descreve o que o mapa deve renderizar, em vez de definir passos processuais para a renderização.
map_json = {
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/map/definition/2.0.0/schema.json",
"basemap": {
"options": {
"style": "road"
}
},
"dataSources": [
{
"itemType": "Lakehouse",
"workspaceId": "<workspace-id>",
"itemId": "<lakehouse-item-id>"
}
],
"layerSources": [
{
"id": "points-source",
"name": "Points-GeoJSON",
"type": "geojson",
"itemId": "<lakehouse-item-id>",
"relativePath": "Files/data/points.geojson",
"refreshIntervalMs": 0
}
],
"layerSettings": [
{
"id": "points-layer",
"name": "Points",
"sourceId": "points-source",
"options": {
"type": "vector",
"visible": True,
"color": "#0078D4",
"pointLayerType": "bubble",
"bubbleOptions": {
"color": "#0078D4"
}
}
}
]
}
Para mais informações sobre os componentes-chave num map.json, veja MapDetails.
Padrão 1: Criar um mapa e depois atribuir a definição
Use este padrão quando precisar de criar primeiro um item de mapa Fabric e aplicar a definição do mapa mais tarde. Esta abordagem é útil quando a definição do mapa é gerada dinamicamente, proveniente de múltiplos ficheiros ou atualizada incrementalmente depois de o item do mapa já existir. Neste padrão, a chamada inicial à API cria o item do mapa apenas com metadados, e uma chamada subsequente atribui uma definição map.json válida para o esquema para configurar o mapa base, as fontes de dados e as camadas.
Observação
Este padrão é tipicamente usado em cenários avançados onde a definição evolui ao longo do tempo ou é montada dinamicamente.
Passo 1: Criar o item do mapa (apenas metadados)
Esta chamada não inclui uma definição de mapa:
import httpx
BASE_URL = "https://api.fabric.microsoft.com"
TOKEN = "<access-token>"
WORKSPACE_ID = "<workspace-id>"
map_name = "Automated Map (Pattern 1)"
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json"
}
# Metadata only – NOT map.json
create_map_payload = {
"displayName": map_name
}
response = httpx.post(
f"{BASE_URL}/workspaces/{WORKSPACE_ID}/items/maps",
headers=headers,
json=create_map_payload,
timeout=30
)
response.raise_for_status()
map_item = response.json()
map_id = map_item["id"]
Neste ponto, o item do mapa existe, mas não tem definição aplicada.
Passo 2: Defina o mapa (map.json)
Prepare uma carga útil map_json válida, como o exemplo mostrado anteriormente.
Passo 3: Atribuir a definição ao mapa
response = httpx.put(
f"{BASE_URL}/workspaces/{WORKSPACE_ID}/items/maps/{map_id}/definition",
headers=headers,
json={
"definition": {
"parts": [
{
"path": "map.json",
"payload": map_json,
"payloadType": "InlineJson"
}
]
}
},
timeout=30
)
response.raise_for_status()
Padrão 2: Criar o mapa com a definição (recomendado)
Use este padrão para criar e configurar o mapa numa única operação.
Esta abordagem é bem adequada para implementações declarativas, como pipelines CI/CD ou fluxos de trabalho de infraestrutura como código.
Requisito Base64
Ao incluir uma definição em chamadas REST, a carga útil deve ser codificada em Base64 e fornecida como parte da definição.
Importante
Se map.json for incluído em qualquer pedido REST, deve ser incluído como uma carga útil codificada em Base64 em definition.parts[] e payloadType: "InlineBase64".
Base64 ajudante
Use este auxiliar para transformar um map.json Python dict na cadeia Base64 exigida por definition.parts[].payload.
import base64
import json
def to_inline_base64(obj: dict) -> str:
"""
Serialize a JSON-compatible dict and return a Base64-encoded UTF-8 string.
Use this for definition.parts[].payload when payloadType is InlineBase64.
"""
raw = json.dumps(obj, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
return base64.b64encode(raw).decode("utf-8")
Criar mapa com definição em linha
O pedido inclui:
-
displayName(metadados dos itens do mapa) -
definition.parts[]onde map.json éBase64-encodede marcado comoInlineBase64
import httpx
BASE_URL = "https://api.fabric.microsoft.com/v1"
TOKEN = "<access-token>"
WORKSPACE_ID = "<workspace-id>"
map_name = "Automated Map (Pattern 2)"
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
}
# Schema-valid map.json (example fields abbreviated here)
map_json = {
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/map/definition/2.0.0/schema.json",
"basemap": {"options": {"style": "road"}},
"dataSources": [
{
"itemType": "KqlDatabase",
"workspaceId": "<workspace-id>",
"itemId": "<eventhouse-or-kql-db-item-id>"
}
],
"layerSources": [
{
"id": "work-orders-src",
"name": "Work orders (Eventhouse)",
"type": "kusto",
"itemId": "<eventhouse-or-kql-db-item-id>",
"refreshIntervalMs": 5000
}
],
"layerSettings": [
{
"id": "work-orders-layer",
"name": "Work orders",
"sourceId": "work-orders-src",
"options": {"type": "vector", "visible": True, "color": "#0078D4"}
}
]
}
payload = {
"displayName": map_name,
"definition": {
"parts": [
{
"path": "map.json",
"payload": to_inline_base64(map_json),
"payloadType": "InlineBase64"
}
]
}
}
with httpx.Client(timeout=60) as client:
response = client.post(
f"{BASE_URL}/workspaces/{WORKSPACE_ID}/maps",
headers=headers,
json=payload,
timeout=30
)
response.raise_for_status()
created = response.json()
map_id = created["id"]
Resumo: Padrão 1 vs Padrão 2 (regra Base64)
Ambos os padrões de criação de mapas dependem, em última análise, do mesmo contrato de definição de mapa, mas diferem quanto ao momento em que a definição é fornecida e quando é necessária a codificação Base64. Esta secção reexamina o Padrão 1 e o Padrão 2 lado a lado para esclarecer uma fonte comum de confusão: Sempre que map.json é incluído numa chamada REST — seja durante a criação ou atualização — deve ser fornecido como uma parte de definição codificada em Base64. Compreender esta distinção ajuda a garantir que os fluxos de trabalho de automação de mapas aplicam o formato correto da carga útil em cada passo e evitam erros subtis no formato do pedido.
Padrão 1: Criar o mapa → depois atribuir definição
- Chamada de Create Map: apenas metadados (sem definição, portanto sem Base64 na altura da criação).
- Atribuir definição: usar Update Map Definition com definition.parts[] e payloadType: "InlineBase64" (portanto, o Base64 é necessário na altura da atualização).
Padrão 2: Criar mapa com definição incluída
-
A chamada Create Map inclui a definição: Forneça
definition.parts[]e codifique em Base64 map.json utilizandopayloadType: "InlineBase64".
Regra geral: Se incluir map.json em qualquer pedido ou resposta REST, leve-o como uma carga útil Base64 numa
definition.parts[]entrada compayloadType: "InlineBase64".
Criar função auxiliar para recuperar o ID do mapa
Quando cria um mapa usando a API Fabric REST, o pedido pode devolver uma resposta 202 Aceite. Esta resposta indica que o mapa está a ser provisionado de forma assíncrona como uma operação de longa duração (LRO), em vez de ser criado imediatamente. Neste caso, a resposta não inclui o ID do mapa, e o endpoint de conclusão do LRO pode não devolver um resultado utilizável. Mesmo após a conclusão da operação, o mapa recém-criado pode não aparecer imediatamente ao chamar a API de Mapas de Listas devido à propagação do backend.
Para obter o ID do mapa de forma fiável, deve consultar a lista de mapas e tentar novamente até que o novo mapa fique visível. A seguinte função auxiliar implementa este padrão de repetição e garante que o seu fluxo de automação seja resiliente a atrasos no provisionamento assíncrono.
# ---------------------------------------------------------
# Get Map ID
# ---------------------------------------------------------
def resolve_map_id(client, list_url, headers, map_name, max_attempts=10, delay=5):
"""
Resolve the ID of a newly created Fabric map.
Why this function is needed:
- Creating a map may return HTTP 202 (Accepted), indicating an asynchronous
long-running operation (LRO) rather than immediate creation.
- LRO responses for map creation don't always return a resource ID.
- Even after the operation completes, the new map may not be immediately
visible in the List Maps API due to backend propagation delays.
What this function does:
- Repeatedly calls the List Maps API.
- Searches for a map matching the provided display name.
- Retries for a configurable number of attempts with a delay between calls.
Parameters:
client : Authenticated HTTP client
list_url : Maps list endpoint
headers : Authorization headers for Fabric API
map_name : Display name of the map to locate
max_attempts : Maximum number of retry attempts
delay : Delay (seconds) between retries
Returns:
The map ID (string) once the map becomes visible.
Raises:
RuntimeError if the map is not found after all retry attempts.
"""
for attempt in range(max_attempts):
print(f"Resolving map (attempt {attempt + 1}/{max_attempts})...")
resp = client.get(list_url, headers=headers)
resp.raise_for_status()
items = resp.json().get("value", [])
match = next(
(m for m in items if m.get("displayName") == map_name),
None
)
if match:
print("✅ Map found!")
return match["id"]
print("⏳ Map not visible yet. Retrying...")
time.sleep(delay)
raise RuntimeError("Map created but still not visible after retries")
Em vez de obter o ID do mapa como no exemplo anterior (map_id = created["id"]), experimente:
if response.status_code == 201:
map_id = response.json()["id"]
elif response.status_code == 202:
print("LRO completed via 202. Resolving map by name...")
map_id = resolve_map_id(
client,
create_map_url,
_fabric_headers(),
map_name
)