Partilhar via


Trabalhar com JSON no Power Fx

O Power Fx permite que os criadores leiam JSON para um Objeto sem tipo utilizando a função ParseJSON.

Ler e converter valores

ParseJSON converterá a seguinte cadeia de registos JSON num Objeto sem tipo com campos ItemName, Quantity, ReleaseDate e AvailableForPreOrder.

{
  "ItemName" : "Widget 1",
  "Quantity" : 46,
  "ReleaseDate" : "2022-09-01",
  "AvailableForPreOrder" : true
}

Cada um dos campos pode ser acedido utilizando a notação de ponto no valor de Objeto sem tipo obtido de ParseJSON.

Set( untyped, ParseJSON( jsonStringVariable ) );

Set( item, Text ( untyped.ItemName ) );
Set( quantity, Value ( untyped.Quantity ) );
Set( release, DateValue ( untyped.ReleaseDate ) );
Set( preorder, Boolean ( untyped.AvailableForPreOrder ) );

Geralmente, é boa ideia converter explicitamente o valor de um objeto sem tipo para um tipo específico. A definição de um objeto sem tipo como um valor variável torna a variável um Objeto sem tipo também. Assim, é provável que seja necessário converter esse valor explicitamente ao definir para uma variável. Mas na maioria dos casos, os valores de objeto sem tipo serão convertidos automaticamente num tipo específico ("coerce") quando utilizados como parâmetros de função, em que o tipo é um tipo simples, tal como booleano, número ou texto, e o perfil do parâmetro da função não tem potenciais sobrecargas conflituantes.

Left( untyped.ItemName, 1 ); // "W"
Radians( untyped.Quantity ); // 0.80285146
If (untyped.AvailableForPreOrder, "Available", "Not Available" ); // "Available"

Além de converter automaticamente o tipo em chamadas de função, os objetos sem tipo também serão convertidos quando atribuídos a propriedades do controlo, sempre que possível.

Label1.Text: untyped.Quantity
InputText1.Default: untyped.ItemName

Por fim, quando utiliza operadores, tais como & ou +, um Objeto sem tipo será forçado se não existir nenhuma ambiguidade no tipo esperado.

untyped.Quantity + 1 // result is a number
untyped.ItemName & " (preorder)" // result is text
untyped.Quantity + untyped.Quantity // result is a number
untyped.Quantity & untyped.ItemName // result is text

Nota

O JSON não tem um tipo GUID, Cor, Hora ou DateTime. Estes valores são representados como uma cadeia. Se atribuir diretamente um valor de objeto sem tipo JSON que contenha uma data para uma propriedade de texto, será utilizado o texto original de JSON. Isto poderá ser importante quando se trata de fusos horário, formatos de data, etc. Nesses casos, deverá converter explicitamente os valores utilizando GUID(), ColorValue(), DateValue(), DateTimeValue(), etc.

Caso um nome de campo seja composto por um nome de identificador inválido, por exemplo, quando os nomes de campo começam por um número ou contêm carateres inválidos, como um hífen, pode colocar os nomes de campo entre plicas:

untyped.'01'
untyped.'my-field'

O Power Fx não avaliará a existência do campo até que a fórmula seja executada. Isto permite flexibilidade no JSON a receber. Por exemplo, o JSON anterior pode, por vezes, conter um campo adicional denominado Discount. No entanto, no nosso exemplo anterior, este campo não está presente. A escrita de uma fórmula que utilize o campo Discount não resultará em erros, durante o processo de criação da aplicação ou quando os utilizadores utilizam a aplicação. Se o campo estiver em falta quando a fórmula for executada, o valor irá apenas resultar num valor Blank().

Nota

JSON suporta valores null para campos. Estes também resultarão em valores Blank(). Atualmente, não existe distinção no Power Fx entre um campo em falta ou um campo que tenha o valor null.

Uma vez que o acesso a campos em Objetos sem tipo não é avaliado ao escrever a fórmula, também não existe Intellisense disponível. Tanto o JSON como o Power Fx são sensível às maiúsculas e minúsculas, por isso, tenha especial cuidado ao escrever nomes de campos.

Os valores JSON não têm de estar numa notação de estilo de registo. O JSON válido pode ser apenas um valor, tal como "text value", true ou 123.456. Neste caso, o Objeto sem tipo que ParseJSON obtém é o valor propriamente dito e a notação de ponto não é utilizada.

Set( myText, Boolean( ParseJSON( "true" ) ) );

Set( myNumber, Value( ParseJSON( "123.456" ) ) );

Por fim, o JSON suporta registos aninhados. Converter este JSON em Objeto sem tipo resulta em objetos aninhados, sendo que a notação de ponto pode ser utilizada para percorrer a hierarquia.

{
  "Version" : 1,
  "RootElement" : {
    "Parent" : {
      "Name" : "This is the parent",
      "Child" : {
        "Name" : "This is the child"
      }
    }
  }
}

Quando converte esta cadeia JSON numa variável de Objeto sem tipo denominada jsonObject, os campos podem ser acedidos através da notação de ponto.

Set( jsonObject, ParseJSON( jsonStringVariable ) );

Set( parentName, Text( jsonObject.RootElement.Parent.Name ) ); // "This is the parent"

Set( childName, Text( jsonObject.RootElement.Parent.Child.Name ) ); // "This is the child"

Se qualquer um dos campos na expressão de notação de ponto não existir, será obtido Blank().

Matrizes e tabelas

O JSON pode conter matrizes de valores ou registos. Estas matrizes podem ser acedidas diretamente ou convertidas em tabelas do Power Fx.

{
  "OrderNumber" : "SO000010",
  "CustomerID" : "CUST0126",
  "OrderLines" : [
    {
      "Item" : "Widget 1",
      "Quantity" : 3
    },
    {
      "Item" : "Widget 2",
      "Quantity" : 5
    }
  ]
}

Este JSON contém um registo com um campo denominado OrderLines que contém uma matriz de registos. Cada registo tem dois campos: Item e Quantity. Se o JSON for convertido num Objeto sem tipo utilizando a função ParseJSON e definir para uma variável denominada jsonOrder, podemos aceder às linhas de encomenda individuais de várias formas.

Set( jsonOrder, ParseJSON( jsonStringVariable ) );

Pode obter registos e valores individuais utilizando a função Index(). Por exemplo, para obter o segundo registo no campo OrderLines, aceda ao campo Quantity e converta-o num valor.

Set( line2Quantity, Value( Index( jsonOrder.OrderLines, 2 ).Quantity ); // 5

É possível converter a matriz de linhas de encomenda diretamente numa tabela. Isto criará uma tabela de coluna única com um Objeto sem tipo que representa o registo.

Set( orderLines, Table( jsonOrder.OrderLines ) );

A tabela de coluna única "orderLines" tem agora uma coluna "Value" que representa o Objeto sem tipo. Para utilizar qualquer um dos campos de um registo nesta tabela, utilize a notação de ponto para aceder ao campo JSON no Objeto sem tipo na coluna Value.

Set( jsonRecord, Index( orderLines, 2 ) ); // Get the second record in the table

Set( line2Item, Text( jsonRecord.Value.Item ) ); // "Widget 2"

Para facilitar e simplificar a utilização dos registos de linha de encomenda noutras partes da aplicação, pode converter o Objeto sem tipo completo num registo com tipo total utilizando a função ForAll(). Fornecer o Objeto sem tipo diretamente para a ForAll() significa que pode aceder diretamente aos campos de objeto, em vez de utilizar o campo Value de coluna única.

Set( typedOrderLines, ForAll( jsonOrder.OrderLines, { Item : Text( ThisRecord.Item ), Quantity : Value( ThisRecord.Quantity ) } ) );

A nova variável typedOrderLines agora é uma tabela Power Fx com tipo total com as seguintes colunas e valores:

Item Quantidade
"Widget 1" 3
"Widget 2" 5

Os exemplos anteriores utilizam matrizes de registos, mas o JSON também pode conter matrizes apenas de valores. Considere o seguinte exemplo que é uma cadeia JSON válida que contém uma matriz de três cadeias.

[ "First Item", "Second Item", "Third Item"]

Podemos obter um dos itens da matriz utilizando a função Index() e convertê-lo em texto.

Text( Index( ParseJSON( jsonStringVariable ), 2 ) ) // "Second Item"