APLデータソースとトランスフォーマー



APLデータソースとトランスフォーマー

データソースとは、APLドキュメントにバインドできるデータのソースを定義するJSON構造のことです。APLドキュメントをAlexaに送信するときに、1つ以上のデータソースを含めることができます。データソースとは、APLドキュメントのパラメーターに名前でバインドされます。ドキュメント内のAPLコンポーネントでは、データバインディングの式を使用して、該当するデータソースを参照できます。

スキル応答のdatasourcesオブジェクト

データソースをAlexaに渡すときに使用するdatasourcesオブジェクトは、RenderDocumentディレクティブの一部ですが、APLドキュメント自体には含まれていません。このdatasourcesオブジェクトには他のオブジェクト(実際のデータソース)のみを含めることができます。

この例では、RenderDocumentディレクティブを使用したスキル応答を示しています。ドキュメントと「myDocumentData」という名前のデータソースがAlexaに渡されます。ドキュメントの内容は、簡潔に示すために省略しています。

{
  "version": "1.0",
  "response": {
    "outputSpeech": {
      "type": "SSML",
      "ssml": "<speak>これは例です</speak>"
    },
    "sessionAttributes": {},
    "directives": [
      {
        "type": "Alexa.Presentation.APL.RenderDocument",
        "token": "[SkillProvidedToken]",
        "document": {},
        "datasources": {
          "myDocumentData": {
            "title": "これはとても単純な例です"
          }
        }
      }
    ]
  }
}

ドキュメントのデータソースにアクセスする

データソースにアクセスするには、APLドキュメントのmainTemplateで、payloadというパラメーターを宣言します。このパラメーターは、応答の中でdatasourcesオブジェクトのルートに割り当てられます。したがって、ドキュメント内から、構文${payload.dataSourceName.propertyName}を使用して、ドキュメント内のプロパティをデータソース内のプロパティにバインドできます。

次の応答ではmyDocumentDataという1つのデータソースにバインドするAPLドキュメントを示しています。この場合、Textコンポーネントのtextプロパティは、myDocumentDataデータソースのtitleプロパティにバインドされています。スキルがこの応答をAlexaに送信すると、デバイスでは「これはとても単純な例です」というテキストが表示されます。

{
  "version": "1.0",
  "sessionAttributes": {},
  "response": {
    "outputSpeech": {
      "type": "SSML",
      "ssml": "<speak>これは例です</speak>"
    },
    "directives": [
      {
        "type": "Alexa.Presentation.APL.RenderDocument",
        "token": "[SkillProvidedToken]",
        "document": {
          "type": "APL",
          "version": "1.0",
          "theme": "auto",
          "import": [
            {
              "name": "alexa-layouts",
              "version": "1.0.0"
            }
          ],
          "resources": [],
          "styles": {},
          "layouts": {},
          "mainTemplate": {
            "parameters": [
              "payload"
            ],
            "items": [
              {
                "type": "Container",
                "width": "100vw",
                "height": "100vh",
                "items": [
                  {
                    "type": "Text",
                    "text": "${payload.myDocumentData.title}"
                  }
                ]
              }
            ]
          }
        },
        "datasources": {
          "myDocumentData": {
            "title": "これはとても単純な例です"
          }
        }
      }
    ]
  }
}

オブジェクト型のデータソース

上記の単純なデータソースは、一連のプロパティを定義する、型付けされていないデータソースの例です。APLでは、定義された構造に従った型付けされたデータソースもサポートしています。これにより、トランスフォーマーを使用してデータを操作するなど、追加機能を利用できるようになります。

サポートされている唯一のデータソースタイプはobjectです。型付けされたデータソースには、以下のプロパティがあります。

プロパティ 必須 説明
type オブジェクト 「オブジェクト」である必要があります。
properties オブジェクト トランスフォーマーで使用できるバインド可能なプロパティを含むオブジェクトです。
objectID 文字列 オブジェクトデータソースの任意の識別子です。
description 文字列 データソースの任意の説明です。
transformers 配列 プロパティオブジェクトの値に適用されるトランスフォーマーの配列です。

この例は、textToSpeechトランスフォーマーを使用したオブジェクトデータソースを示しています。トランスフォーマーはpropertiesオブジェクト内のデータを参照します。トランスフォーマーの使用方法について詳しくは、後述のトランスフォーマーを参照してください。

{
  "myDocumentData": {
    "type": "object",
    "properties": {
      "title": "これはとても単純な例です。",
      "mainText": "これらのプロパティは<code>properties</code>オブジェクトにあります。"
    },
    "transformers": [
      {
        "inputPath": "title",
        "outputName": "titleSpeech",
        "transformer": "textToSpeech"
      }
    ]
  }
}

トランスフォーマー

トランスフォーマーは、データソースのデータを別の表現に変換します。RenderDocumentディレクティブは、次の4つのトランスフォーマーをサポートしています。

  • ssmlToSpeech: 音声合成マークアップ言語(SSML)の入力値を、APLコンポーネントのspeechプロパティにバインドできる音声に変換します。その後、SpeakItem APLコマンドを使用して、コンポーネントに関連付けられた音声を読み上げることができます。audioタグssmlToSpeechトランスフォーマーと一緒に使うことはできません。このトランスフォーマーに渡されるテキストは、<speak>タグで囲まれた有効なSSMLである必要があります。
  • ssmlToText: 入力したSSMLをプレーンテキストに変換します。
  • textToHint: 入力された値を、デバイスに応じた正しいウェイクワードとヒント(「アレクサ、ヒントです」と言ってみて)に変換します。デバイスに応じたウェイクワードを選択できるので、ヒントに「アレクサ」という語をハードコーディングしないでください。
  • textToSpeech: 入力したプレーンテキストをAPLコンポーネントのspeechプロパティにバインドできる音声に変換します。その後、SpeakItem APLコマンドを使用して、コンポーネントに関連付けられた音声を読み上げることができます。

トランスフォーマーのプロパティと変換規則

トランスフォーマーはデータソース内の名前付きプロパティのデータ変換を実行して、元のデータソースのプロパティにデータを書き込みます。outputNameが指定されていない場合、トランスフォーマーはinputプロパティを上書きします。すべてのトランスフォーマーには、次の表に示す基本プロパティがあります。

プロパティ 必須 説明
transformer 文字列 トランスフォーマーのタイプです。
inputPath 文字列 オブジェクト内の、変換するコンテンツへのパスです。データソースのpropertiesオブジェクト内のプロパティを参照する必要があります。
outputName 文字列 オブジェクトに追加されるプロパティの名前です。outputNameが指定されていない場合、inputPathは変換された出力で上書きされます。

inputPathは、データソースオブジェクトの1つのエンティティを指すか、ワイルドカードのプロパティまたは未解決配列を使用している一連のエンティティを指します。inputPathと一致するプロパティが変換されます。inputPathパターンはシンボルで、一定数のノードまたはワイルドカード参照が後に続きます。

次のルールが適用されます。

  • シンボル名または配列インデックスは、プロパティブロック内の既存のオブジェクトプロパティまたは配列インデックスと一致する必要があります。一致しない場合、変換は破棄されます。

  • 出力が保存されている場所は、ワイルドカード以外の最後のノードをoutputNameで置き換えることで見つけられます。ワイルドカード以外のノードがない場合は、シンボルはoutputNameで置き換えられます。

  • 最後のワイルドカード以外のノードが数値インデックスになることはありません。最後のワイルドカード以外のノードが数値の場合は、変換は破棄されます。

これらの例は、参照のしくみを示しています。次のサンプルデータを考えてみましょう。

{
  "myDocumentData": {
    "type": "object",
    "properties": {
      "name": "山田太郎",
      "address": {
        "street": "中央通り301番地",
        "city": "目黒区"
      },
      "family": [
        {
          "name": "花子",
          "relation": "妻"
        },
        {
          "name": "桜子",
          "relation": "娘"
        }
      ],
      "contacts": [
        "鈴木一郎",
        "鈴木梅子"
      ]
    },
    "transformers": [
      {
        "inputPath": ["see examples in table below"],
        "outputName": ["see examples in table below"],
        "transformer": "textToSpeech"
      }
    ]
  }
}

次の表は、inputPathoutputNameのさまざまな値によって、上記のデータソースのデータがどのように変換されるかを示しています。

inputPath 変換される項目 結果の保存場所
name "山田太郎" outputName
address.street "中央通り301番地" address.outputName
contacts.* ["鈴木一郎", "鈴木梅子"] outputName[0], outputName[1]
family[0].name "花子" family[0].outputName
family[*].name "花子", "桜子" family[0].outputName, family[1].outputName
address.* "中央通り301番地", "目黒区" outputName.street, outputName.city
family[3].name   無効:family配列にはインデックス3の値が指定されていません。
family[1].names   無効:family[1]の値にはnamesプロパティが指定されていません。
family[0] { "name": "花子", "relation": "妻" } 無効:最後のワイルドカード以外のノードが数値インデックスになることはありません。

ssmlToSpeechトランスフォーマー

ssmlToSpeechトランスフォーマーは、SSML文字列を音声に適したエンティティに変換します。このトランスフォーマーに渡されるテキストは、<speak>タグで囲まれた有効なSSMLである必要があります。プレーンテキストの場合は、代わりにtextToSpeechトランスフォーマーを使用してください。

ドキュメントにおいて、ssmlToSpeechトランスフォーマーの出力値をコンポーネントのspeechプロパティにバインドします。下記のコードは、猫の秘密にバインドされたTextコンポーネントに音声を関連付けた「猫の秘密」スキルを示しています。

textプロパティはcatFactData.properties.catFactを指し、speechコンポーネントはcatFactData.properties.catFactSpeechを指します。

{
  "type": "Container",
  "item": {
    "type": "Text",
    "id": "catFactText",
    "text": "${payload.catFactData.properties.catFact}",
    "speech": "${payload.catFactData.properties.catFactSpeech}"
  }
}

次の例は、対応するcatFactDataデータソースを示しています。propertiesオブジェクトには、コンポーネントで使用する実際のテキストを含むcatFactSsmlプロパティがあります。このプロパティは、ssmlToSpeechおよびssmlToTextトランスフォーマーの両方の入力値として使用されます。

  • ssmlToSpeechトランスフォーマーは、catFactSsmlの値を音声に変換し、その出力値をcatFactSpeechという新しいプロパティに格納します。catFactSpeechプロパティは、前述のTextコンポーネントのspeechプロパティにバインドされています。
  • ssmlToTextトランスフォーマーは、catFactSsmlの値をプレーンテキストに変換し、出力値をcatFactという新しいプロパティに配置します。catFactプロパティは、前述のTextコンポーネントのtextプロパティにバインドされています。
{
  "catFactData": {
    "type": "object",
    "properties": {
      "backgroundImage": "https://.../catfacts.png",
      "title": "猫の秘密 #9",
      "logoUrl": "https://.../logo.png",
      "image": "https://.../catfact9.png",
      "catFactSsml": "<speak>すべての猫が<emphasis level='strong'>マタタビ</emphasis>を好むとは限りません。</speak>"
    },
    "transformers": [
      {
        "inputPath": "catFactSsml",
        "outputName": "catFactSpeech",
        "transformer": "ssmlToSpeech"
      },
      {
        "inputPath": "catFactSsml",
        "outputName": "catFact",
        "transformer": "ssmlToText"
      }
    ]
  }
}

最後に、猫の秘密を読み上げるには、SpeakItemコマンドで使用して、AlexaにAlexa.Presentation.APL.ExecuteCommandsディレクティブを送信します。下記のコードは、猫の秘密を読み上げるために使用できるAlexa.Presentation.APL.ExecuteCommandsディレクティブを示します。ExecuteCommandsディレクティブで渡しているトークンは必須です。このトークンは、APLドキュメントの表示に使用するRenderDocumentディレクティブでスキルによって渡されるトークンと一致する必要があります。

{
  "type": "Alexa.Presentation.APL.ExecuteCommands",
  "token": "[SkillProvidedToken]",
  "commands": [
    {
      "type": "SpeakItem",
      "componentId": "catFactText",
      "highlightMode": "line",
      "align": "center"
    }
  ]
}

ssmlToTextトランスフォーマー

SSMLからテキストに変換するトランスフォーマーは、SSMLマークアップを削除することで、すべてのSSMLテキスト文字列を人が読みやすいテキストに変換します。

textToHintトランスフォーマー

textToHintトランスフォーマーは入力された値を、デバイスに応じた正しいウェイクワードとヒント(「アレクサ、ヒントです」を言ってみて)に変換します。デバイスに応じたウェイクワードを選択できるので、ヒントに「アレクサ」という語をハードコーディングしないでください。通常、このトランスフォーマーはAlexaFooterレスポンシブ対応コンポーネントと共に使用します。

ヒントの表示例については、textToHintトランスフォーマーを使用するを参照してください。

textToSpeechトランスフォーマー

textToSpeechトランスフォーマーは、プレーンテキストを音声に適したエンティティに変換します。このトランスフォーマーに渡されるテキストは、プレーンテキストでなければなりません。SSMLテキストの場合は、代わりにssmlToSpeechトランスフォーマーを使用してください。

このトランスフォーマーは、ssmlToSpeechトランスフォーマーと同じように機能します。textToSpeechトランスフォーマーの出力値をコンポーネントのspeechプロパティにバインドして、SpeakItemコマンドを使用してテキストを読み上げます。

このデータソースの例では、前述のcatFactDataデータソースを示していますが、catFactTextプロパティにはプレーンテキストを使用しています。この場合、catFactTextプロパティは既にプレーンテキストであるため、ssmlToTextトランスフォーマーは不要です。

{
  "catFactData": {
    "type": "object",
    "properties": {
      "backgroundImage": "https://.../catfacts.png",
      "title": "猫の秘密 #9",
      "logoUrl": "https://.../logo.png",
      "image": "https://.../catfact9.png",
      "catFactText": "すべての猫がマタタビを好むとは限りません。"
    },
    "transformers": [
      {
        "inputPath": "catFactText",
        "outputName": "catFactSpeech",
        "transformer": "textToSpeech"
      }
    ]
  }
}

Textコンポーネントでは、このデータソースを次のように参照できます。

{
  "type": "Container",
  "item": {
    "type": "Text",
    "id": "catFactText",
    "text": "${payload.catFactData.properties.catFactText}",
    "speech": "${payload.catFactData.properties.catFactSpeech}"
  }
}

textプロパティは、変換されていないプレーンテキストのcatFactTextプロパティにバインドします。speechプロパティはトランスフォーマーの出力値にバインドします。