分享方式:


在 Power Fx 中使用 JSON

Power Fx 可讓製作者使用 ParseJSON 函數將 JSON 讀取至非類型化物件

讀取與轉換值

ParseJSON 會將以下 JSON 記錄字串轉換為 an 非類型化物件 with fields ItemNameQuantity,and ReleaseDate AvailableForPreOrder

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

可以使用從 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 ) );

將非類型化物件的值明確轉換為特定類型,通常是不錯的做法。 將非類型化物件設定為變數值,也會讓變數變成非類型化物件。 因此,可能需要在設定為變數時明確轉換此類值。 但在大多數情況下,非類型化物件值會在當做函數參數時,自動轉換為特定類型 (「強制轉型」),其中類型是布林值、數字或文字等簡單類型,而且函數的參數設定檔沒有潛在的衝突多載。

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

除了自動轉換函數呼叫中的類型之外,將非類型化物件指派至控制項屬性時,也會盡可能進行轉換。

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

最後,當使用運算子時 (如 &+),如果預期類型沒有歧義,則將強制使用非類型化物件

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

注意

JSON 沒有 GUID、 ColorTimeDateTime 類型。 這些值會以字串表示。 如果您將包含日期的 JSON 非類型化物件值直接指派至文字屬性,則會使用 JSON 的原始文字。 這在處理時區、日期格式等資料時可能會很重要。在這類情況中,您必須使用 GUID()ColorValue()DateValue()DateTimeValue() 等函數明確進行值轉換。

如果欄位名稱包含無效的標識符名稱,例如當字段名稱以數字開頭或包含無效字符 (如連字符) 時,您可以將欄位名稱放在單引號中:

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

在執行公式之前,Power Fx 不會評估欄位是否存在。 這樣在接收 JSON 時會比較有彈性。 例如,先前的 JSON 有時可能包含名為 Discount 的額外欄位。 但是在先前的範例中,這個欄位並不存在。 編寫使用 Discount 欄位的公式不會導致任何錯誤,無論是在應用程式製作過程中還是在使用者使用應用程式時。 如果執行公式時缺少該欄位,則該值將只會產生 Blank() 值。

注意

JSON 支援 null 欄位的值。 這也會產生 Blank() 值。 目前在 Power Fx 中,缺少欄位或值為null 的欄位沒有區別。

由於在編寫公式時不會評估存取非類型化物件上的欄位,因此也沒有 Intellisense 可用。 JSONPower Fx都區分大小寫,因此在填寫欄位名稱時要格外小心。

JSON 值不必採用記錄樣式表示法。 有效的 JSON 可以只是一個值,例如 "text value"true123.456。 在這種情況下,ParseJSON 傳回的非類型化物件就是值本身,且不會使用點標記法。

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

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

最後,JSON 支援巢狀記錄。 將此類 JSON 轉換成非類型化物件會產生巢狀物件,並且可以使用點標記法來周遊階層。

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

將此 JSON 字串轉換成名為 jsonObject非類型化物件變數時,可以使用點標記法存取欄位。

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"

如果點標記法運算式中的所有欄位都不存在,將會傳回 Blank()

陣列和資料表

JSON 可以包含值或記錄的陣列。 您可以直接存取這些陣列,也可以將其轉換為 Power Fx 資料表。

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

JSON 包含一個記錄,其中包含一個名為 OrderLines 的欄位,該欄位包含一個記錄陣列。 每個記錄有兩個欄位:ItemQuantity。 如果使用 ParseJSON 函數將 JSON 轉換成非類型化物件,並將其設定成名為 jsonOrder 的變數,則可使用多種方式存取各訂單行。

Set( jsonOrder, ParseJSON( jsonStringVariable ) );

您可以使用 Index() 函數來擷取個別記錄和值。 例如,若要取得 OrderLines 欄位中的第二個記錄,請存取 Quantity 欄位並將其轉換為值。

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

您可以將訂單行陣列直接轉換成資料表。 這將建立一個具有非類型化物件表示記錄的單一資料行資料表。

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

單一資料行資料表 'orderLines' 現在有一個 'Value' 資料行,表示非類型化物件。 若要使用此資料表記錄中的任何欄位,請使用點標記法來存取 Value 資料行中非類型化物件上的特定 JSON 欄位。

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

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

為了讓您應用程式的其他部分更輕鬆、更直接地使用訂單行記錄,您可以使用 ForAll() 函數將整個非類型化物件轉換為完整類型化記錄。 將非類型化物件直接提供給 ForAll(),即表示您可以直接存取物件欄位,而不是使用單一資料行 Value 欄位來存取。

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

新的 typedOrderLines 變數現在變成完整類型化 Power Fx 資料表,且具有下列資料行和值:

項目 數量
"Widget 1" 3
"Widget 2" 5

上述範例使用的是記錄陣列,但是 JSON 也可以包含只有值的陣列。 請參考下列範例,這是包含三個字串陣列的有效 JSON 字串。

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

我們可以使用 Index() 函數來擷取陣列中的其中一個項目,並將其轉換成文字。

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