使用 JSON 函数

FileMaker Pro 提供若干个文本函数,您的定制化 App 可通过这些函数从其他源解析和修改 JSON 数据,如通过 REST API 传输 JSON 格式数据的 Web 服务。

有关 JSON 数据格式的更多信息,请参阅 json.org

格式化 JSON 数据

JSON 数据不需要元素之间有空格或行结束符。但是,为了使数据在您调试问题时更易读,请使用 JSONFormatElements 函数,该函数会添加制表符和行结束符,如JSON 数据示例中所示。

解析 JSON 数据

使用以下 JSON 函数解析 JSON 数据—即,要获得键、值或您可以进一步处理的全部 JSON 对象或数组:

  • JSONGetElement – 在 JSON 数据中查询元素(对象、数组或值)

  • JSONListKeys – 列出 JSON 数据中的对象名称(键)或数组索引

  • JSONListValues – 列出 JSON 数据中的值

这些函数的第一个参数 json 指定包含要操作的有效 JSON 数据的文本字段、变量或文本表达式。

第二个参数键或索引或路径指定要操作的 JSON 数据的部分:

  • 键 – JSON 对象中键的名称

  • 索引 – JSON 数组中元素的索引(第一个元素的索引为 0)

  • 路径 – 键名称、数组索引或二者的层级字符串

支持以下两种用于 键或索引或路径 参数的语法:点表示法括号表示法

键或索引或路径 参数的语法

表示

点表示法 括号表示法

"."

""

如果是第一个字符,则为根级别(在点表示法中可选)

".[n]"

"[n]"

根级别数组的索引 n 处的元素

".name"

"['name']"

位于根级别的名为 name 的对象的关键字

".nameA.nameB.nameC"

"['nameA']['nameB']['nameC']"

名为 nameC 的对象,其为 nameBnameA 的后代

".[3][2][1]nameA[0]"

"[3][2][1]['nameA'][0]"

nameA 对象中数组的第一个元素,其在一组嵌套数组中位于第三个级别

点与括号表示法之间的差异在于,括号表示法不使用点 (.) 来分隔键名称,而使用单引号 (') 和括号 ([]) 来括住键名称。您可以在 键或索引或路径 中使用任一表示法。但如果键名称包含点,则必须使用括号表示法,以便 JSON 解析程序可以正确识别整个键名称。例如,如果JSON 对象根的键是 "layout.response",则 键或索引或路径 将是 "['layout.response']"。

以下示例脚本为 JSON 数组中的每个产品创建记录。假设JSON 数据示例存储在 $$JSON 变量中,则脚本使用 JSONListValues 来获取产品数组的内容,将其显示值列表,并且使用 ValueCount 来确定列表中的产品数。每次通过循环创建产品记录时,脚本都会使用 GetValue 获取列表中产品的 JSON 对象,并将字段设置为使用 JSONGetElement 获取的值。由于 JSON 函数会解析传递给它们的整个 JSON 对象,在多次重复的循环内较小的 JSON 对象上使用 JSON 函数可能更有效。

复制
设置变量 [ $ProductList ; 值:JSONListValues ( $$JSON ; "面包店.产品" ) ]
设置变量 [ $产品数量 ; 值:ValueCount ( $ProductList ) ]
设置变量 [ $i; 值:1 ]
If [ $产品数量 > 0 ]
   Loop
      新建记录/请求
      设置变量 [ $Product ; 值:GetValue ( $ProductList ; $i ) ]
      设置字段 [ 产品::ID ; JSONGetElement ( $Product ; "id" ) ]
      设置字段 [ 产品::价格 ; JSONGetElement ( $Product ; "价格" ) ]
      设置字段 [ 产品::现货 ; JSONGetElement ( $Product ; "现货" ) ]
      提交记录/请求 [ 包括对话框:Off ]
      设置变量 [ $i ; 值: $i + 1 ] 
      Exit Loop If [ $i > $产品数量 ]
   End Loop 
End If

更改和添加 JSON 数据元素

要在 JSON 数据中更改值并添加元素,请使用JSONSetElement 函数json键或索引或路径参数在此函数中像解析 JSON 数据所描述的那样运行。如果键或索引或路径指定现有元素,则该元素的值将被更改;如果元素不存在,会添加一个新元素。

JSONSetElement 将指定的元素设置为参数。您可以指定从简单字符串或数字到复杂对象或数组的任何有效的 JSON 值。

类型参数指定中的数据类型,以使 JSON 分析器在处理每种数据类型时都将遵循限制规则。有关支持的数据类型,请参阅JSONSetElement 函数。要将数据插入到已设置为有效 JSON 元素格式的 json 中,请将类型设置为 JSONRaw

下面的示例将新产品的键值对添加到空的 JSON 对象中。然后,新对象添加到 $$JSON 变量中产品数组的末尾(请参阅 JSON 数据示例)。

复制
设置变量 [ $NewProduct ; 值:
   JSONSetElement ( "{}" ;
      [ "id" ; "FB4" ; JSONString ] ; 
      [ "名称" ; "面包圈" ; JSONString ] ; 
      [ "价格" ; 17.5 ; JSONNumber ] ; 
      [ "现货" ; 12 ; JSONNumber ] ; 
      [ "类别" ; "面包" ; JSONString ] ; 
      [ "特价" ; true ; JSONBoolean ] 
   ) ]
设置变量 [ $NextIndex ; 值:
   ValueCount ( 
      JSONListKeys ( $$JSON ; "面包店.产品" ) 
   ) ] 
设置变量 [ $$JSON ; 值:
   JSONSetElement ( 
      $$JSON ; "面包店.产品[" & $NextIndex & "]" ; $NewProduct ; 
      JSONObject 
   ) ]

删除 JSON 数据元素

要删除元素,请使用 JSONDeleteElement 函数json键或索引或路径参数在此函数中像解析 JSON 数据所描述的那样运行。键或索引或路径参数必须指定 json 中的现有元素。

以下示例将删除产品数组中“id”键在 $$JSON 变量中的值为“FB3”的元素(请参阅 JSON 数据示例)。

复制
设置变量 [ $产品数量 ; 值:
   ValueCount ( 
      JSONListKeys ( $$JSON ; "面包店.产品" ) 
   ) ] 
设置变量 [ $i ; 值:0 ]
If [ $产品数量 > 0 ]
   Loop
      设置变量 [ $ID ; 值:
         JSONGetElement ( $$JSON ; "面包店.产品[" & $i & "]id" ) ]
      If [ $ID = "FB3" ]
         设置变量 [ $$JSON ; 值:
            JSONDeleteElement ( $$JSON ; "面包店.产品[" & $i & "]" ) ]
         退出脚本 [ 文本结果:0 ]
      End If
      设置变量 [ $i ; 值: $i + 1 ]
      Exit Loop If [ $i ≥ $产品数量 ]
   End Loop
End If

处理 JSON 数据中的错误

如果在解析 json 参数时出错,JSON 函数会返回"?",后面跟着一条来自 JSON 分析器的错误消息。

例如,如果 JSON 数据示例中“面包店”键后面缺少“ :”,则计算

复制
JSONGetElement ( $$JSON ; "面包店.产品[0]id" )

返回下面的错误消息:

复制
? * Line 3, Column 2
  Missing ':' after object member name
* Line 13, Column 5
  Extra non-whitespace after JSON value.

要在使用 JSON 数据之前确定其是否有效,请使用 JSONFormatElements 函数并测试第一个字符是否为 "?"。例如:

复制
设置变量 [ $结果 ; 值:JSONFormatElements ( $$JSON ) ]
If [ Left ($结果 ; 1) = "?"]
   # $$JSON 包含无效 JSON 数据。
End If

或者,要在使用 JSON 数据前确定其是否有效,请使用 JSONGetElementType 函数以测试整个对象是否为 JSON 对象。例如:

复制
设置变量 [ $结果 ; 值:JSONGetElementType ( $$JSON, "" ) ]
If [ $result ≠ JSONObject ]
    # $$JSON 包含无效 JSON 数据。
End If 

从 Web 服务检索 JSON 数据

使用从 URL 插入脚本步骤访问 Web 服务,指定要检索的信息的参数,发送和接收 HTTP 标头,并在变量或字段中存储结果。

例如,一家面包店通过 REST API 采用 JSON 格式使其产品列表可用于客户。以下脚本将当日特价列表作为 $$JSON 变量中的 JSON 数据返回:

复制
设置变量 [ $url ; "https://bakery.example.com/rest/api/products" ]
复制
从 URL 插入 [ 包括对话框:Off; Target: $$JSON ; $url ; 验证 SSL 证书 ; cURL 选项: "--data list=特价" ]

有关在 $$JSON 中返回的数据,请参阅JSON 数据示例

FileMaker Pro 还提供若干个实用程序功能,用来处理一些 REST API 所需的字符编码和加密签名:

JSON 数据示例

以下 JSON 数据示例包含一个“面包店”对象,其包含由三个“产品”对象组成的数组,每个对象都有几个键值对。

复制
{
    "面包店" :
    {
        "产品" :
        [
            {
                "id" :"FB1",
                "名称" :"面包圈",
                "价格" :1.99,
                "现货" :43,
                "类别" :"面包",
                "特价" :真
            },
            {
                "id" :"FB2",
                "价格" :22.5,
                "名称" :"巧克力蛋糕",
                "现货" :23,
                "类别" :"蛋糕",
                "特价" :真
            },
            {
                "id" :"FB3",
                "价格" :3.95,
                "名称" :"法棍面包",
                "现货" :34,
                "类别" :"面包",
                "特价" :真
            }
        ]
    }
}

注释 

  • JSON 分析器保留数组中元素的顺序,但不保留对象中元素的顺序。因此,JSON 函数返回对象中的元素的顺序可能与指定的顺序不同。

  • 在 JSON 数据中,分数数值必须使用句点“.”作为小数点分隔符,而与您计算机的系统格式指定的分隔符或者创建 FileMaker Pro 文件时使用的格式无关。