您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

使用 JSON 架构定义表单Define a form using JSON schema

备注

本主题适用于 SDK v3 版本。This topic applies to SDK v3 release. 可以在此处找到最新版 SDK (v4) 的文档。You can find the documentation for the latest version of the SDK v4 here.

如果使用 FormFlow 创建机器人时使用 C# 类来定义表单,则表单派生自 C# 中类型的静态定义。If you use a C# class to define the form when you create a bot with FormFlow, the form derives from the static definition of your type in C#. 或者,可以改而使用 JSON 架构来定义表单。As an alternative, you may instead define the form by using JSON schema. 使用 JSON 架构定义的表单是纯数据驱动的,只需通过更新架构就可以更改表单(因此,也可以更改机器人的行为)。A form that is defined using JSON schema is purely data-driven; you can change the form (and therefore, the behavior of the bot) simply by updating the schema.

JSON 架构描述了 JObject 中的字段,并包含控制提示、模板和术语的批注。The JSON schema describes the fields within your JObject and includes annotations that control prompts, templates, and terms. 要使用 JSON 架构与 FormFlow,必须将 Microsoft.Bot.Builder.FormFlow.Json NuGet 包添加到项目中,并导入 Microsoft.Bot.Builder.FormFlow.Json 命名空间。To use JSON schema with FormFlow, you must add the Microsoft.Bot.Builder.FormFlow.Json NuGet package to your project and import the Microsoft.Bot.Builder.FormFlow.Json namespace.

标准关键字Standard keywords

FormFlow 支持这些标准 JSON 架构关键字:FormFlow supports these standard JSON Schema keywords:

关键字Keyword 说明Description
typetype 定义字段包含的数据类型。Defines the type of data that the field contains.
枚举enum 定义字段的有效值。Defines the valid values for the field.
minimumminimum 定义字段允许的最小数值(如 NumericAttribute 中所述)。Defines the minimum numeric value allowed for the field (as described in NumericAttribute).
maximummaximum 定义字段允许的最大数值(如 NumericAttribute 中所述)。Defines the maximum numeric value allowed for the field (as described in NumericAttribute).
必填required 定义哪些字段是必填。Defines which fields are required.
patternpattern 验证字符串值(如 PatternAttribute 中所述)。Validates string values (as described in PatternAttribute).

JSON 架构扩展Extensions to JSON Schema

FormFlow 扩展了标准 JSON 架构以支持其他数个属性。FormFlow extends the standard JSON Schema to support several additional properties.

架构根处的其他属性Additional properties at the root of the schema

propertiesProperty Value
OnCompletionOnCompletion 带参数 (IDialogContext context, JObject state) 的 C# 脚本,用于完成表单。C# script with arguments (IDialogContext context, JObject state) for completing the form.
参考References 要包含在脚本中的引用。References to include in scripts. 例如,[assemblyReference, ...]For example, [assemblyReference, ...]. 路径应为当前目录的绝对或相对路径。Paths should be absolute or relative to the current directory. 默认情况下,脚本包括 Microsoft.Bot.Builder.dllBy default, the script includes Microsoft.Bot.Builder.dll.
导入Imports 要包含在脚本中的导入。Imports to include in scripts. 例如,[import, ...]For example, [import, ...]. 默认情况下,脚本包括 Microsoft.Bot.BuilderMicrosoft.Bot.Builder.DialogsMicrosoft.Bot.Builder.FormFlowMicrosoft.Bot.Builder.FormFlow.AdvancedSystem.Collections.GenericSystem.Linq 命名空间。By default, the script includes the Microsoft.Bot.Builder, Microsoft.Bot.Builder.Dialogs, Microsoft.Bot.Builder.FormFlow, Microsoft.Bot.Builder.FormFlow.Advanced, System.Collections.Generic, and System.Linq namespaces.

架构根处的其他属性或作为类型属性对等项的其他属性Additional properties at the root of the schema or as peers of the type property

propertiesProperty Value
模板Templates { TemplateUsage: { Patterns: [string, ...], <args> }, ...}
PromptPrompt { Patterns:[string, ...] <args>}

若要指定 JSON 架构中的模板和提示,请使用 TemplateAttributePromptAttribute 定义的相同词汇。To specify templates and prompts in JSON schema, use the same vocabulary as defined by TemplateAttribute and PromptAttribute. 架构中的属性名称和值应匹配基础 C# 枚举中的属性名称和值。Property names and values in the schema should match the property names and values in the underlying C# enumeration. 例如,此架构片段定义了一个替代 TemplateUsage.NotUnderstood 的模板,并指定了 TemplateBaseAttribute.ChoiceStyleFor example, this schema snippet defines a template that overrides the TemplateUsage.NotUnderstood template and specifies a TemplateBaseAttribute.ChoiceStyle:

"Templates":{ "NotUnderstood": { "Patterns": ["I don't get it"], "ChoiceStyle":"Auto"}}

作为类型属性对等项的其他属性Additional properties as peers of the type property

propertiesProperty 目录Contents 说明Description
DateTimeDateTime boolbool 表示字段是否为 DateTime 字段。Indicates whether field is a DateTime field.
DescribeDescribe 字符串或对象string or object DescribeAttribute 中所述的字段说明。Description of a field as described in DescribeAttribute.
术语Terms [string,...] 如 TermsAttribute 中所述的匹配字段值的正则表达式。Regular expressions for matching a field value as described in TermsAttribute.
MaxPhraseMaxPhrase intint 通过 Language.GenerateTerms(string, int) 运行你的术语来将其展开。Runs your terms through Language.GenerateTerms(string, int) to expand them.
Values { string: {Describe:string | object, Terms:[string, ...], MaxPhrase}, ...}
活动Active 脚本script 带参数 (JObject state)->bool 的 C# 脚本,用来测试字段、消息或确认是否可用。C# script with arguments (JObject state)->bool to test whether the field, message, or confirmation is active.
验证Validate 脚本script 带参数 (JObject state, object value)->ValidateResult 的 C# 脚本,用来验证字段值。C# script with arguments (JObject state, object value)->ValidateResult for validating a field value.
定义Define 脚本script 带参数 (JObject state, Field<JObject> field) 的 C# 脚本,用来动态定义字段。C# script with arguments (JObject state, Field<JObject> field) for dynamically defining a field.
NextNext 脚本script 带参数 (object value, JObject state) 的 C# 脚本,用来在填写字段后确定下一步。C# script with arguments (object value, JObject state) for determining the next step after filling in a field.
之前Before [confirm | message, ...]
之后After [confirm | message, ...]
依赖项Dependencies [string, ...][string, ...] 此字段、消息或确认所依赖的字段。Fields that this field, message, or confirmation depends on.

在 Before 属性或 After 属性的值内使用 {Confirm:script|[string, ...], ...templateArgs} 来定义确认,方法是使用带参数 (JObject state) 的 C# 脚本,或使用随可选模板参数一起随机选择的一组模式 。Use {Confirm:script|[string, ...], ...templateArgs} within the value of the Before property or the After property to define a confirmation by using either a C# script with argument (JObject state) or a set of patterns that will be randomly selected with optional template arguments.

在 Before 属性或 After 属性的值内使用 {Message:script|[string, ...] ...templateArgs} 来定义消息,方法是使用带参数 (JObject state) 的 C# 脚本,或使用随可选模板参数一起随机选择的一组模式 。Use {Message:script|[string, ...] ...templateArgs} within the value of the Before property or the After property to define a message by using either a C# script with argument (JObject state) or a set of patterns that will be randomly selected with optional template arguments.

脚本Scripts

上述几个属性包含脚本作为属性值。Several of the properties that are described above contain a script as the property value. 脚本可以是通常会在方法正文中找到的任何 C# 代码片段。A script can be any snippet of C# code that you might normally find in the body of a method. 可以通过使用 References 属性和/或 Imports 属性来添加引用 。You can add references by using the References property and/or the Imports property. 特殊的全局变量包括:Special global variables include:

变量Variable 说明Description
choicechoice 用于要执行的脚本的内部调度。Internal dispatch for the script to execute.
statestate 所有脚本的绑定的 JObject 表单状态。JObject form state bound for all scripts.
ifieldifield IField<JObject> 可允许对所有脚本(消息/确认提示生成器除外)的当前字段进行推理。IField<JObject> to allow reasoning over the current field for all scripts except Message/Confirm prompt builders.
value 要为 Validate 进行验证的对象值 。Object value to be validated for Validate.
字段field Field<JObject> 可允许动态更新 Define 中的字段。Field<JObject> to allow dynamically updating a field in Define.
上下文context IDialogContext 上下文可允许在 OnCompletion 中发布结果。IDialogContext context to allow posting results in OnCompletion.

通过 JSON 架构定义的字段具有与任何其他字段相同的以编程方式扩展或替代定义的功能。Fields that are defined via JSON schema have the same ability to extend or override the definitions programatically as any other field. 它们也可以用相同的方式进行本地化。They can also be localized in the same way.

JSON 架构示例JSON schema example

定义表单最简单的方法是直接在 JSON 架构中定义所有内容,包括任何 C# 代码。The simplest way to define a form is to define everything, including any C# code, directly in the JSON schema. 此示例显示了使用 FormBuilder 自定义表单中描述的带注释的三明治机器人的 JSON 架构。This example shows the JSON schema for the annotated sandwich bot that is described in Customize a form using FormBuilder.

{
  "References": [ "Microsoft.Bot.Sample.AnnotatedSandwichBot.dll" ],
  "Imports": [ "Microsoft.Bot.Sample.AnnotatedSandwichBot.Resource" ],
  "type": "object",
  "required": [
    "Sandwich",
    "Length",
    "Ingredients",
    "DeliveryAddress"
  ],
  "Templates": {
    "NotUnderstood": {
      "Patterns": [ "I do not understand \"{0}\".", "Try again, I don't get \"{0}\"." ]
    },
    "EnumSelectOne": {
      "Patterns": [ "What kind of {&} would you like on your sandwich? {||}" ],
      "ChoiceStyle": "Auto"
    }
  },
  "properties": {
    "Sandwich": {
      "Prompt": { "Patterns": [ "What kind of {&} would you like? {||}" ] },
      "Before": [ { "Message": [ "Welcome to the sandwich order bot!" ] } ],
      "Describe": { "Image": "https://placeholdit.imgix.net/~text?txtsize=16&txt=Sandwich&w=125&h=40&txttrack=0&txtclr=000&txtfont=bold" },
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "BLT",
        "BlackForestHam",
        "BuffaloChicken",
        "ChickenAndBaconRanchMelt",
        "ColdCutCombo",
        "MeatballMarinara",
        "OvenRoastedChicken",
        "RoastBeef",
        "RotisserieStyleChicken",
        "SpicyItalian",
        "SteakAndCheese",
        "SweetOnionTeriyaki",
        "Tuna",
        "TurkeyBreast",
        "Veggie"
      ],
      "Values": {
        "RotisserieStyleChicken": {
          "Terms": [ "rotis\\w* style chicken" ],
          "MaxPhrase": 3
        }
      }
    },
    "Length": {
      "Prompt": {
        "Patterns": [ "What size of sandwich do you want? {||}" ]
      },
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "SixInch",
        "FootLong"
      ]
    },
    "Ingredients": {
      "type": "object",
      "required": [ "Bread" ],
      "properties": {
        "Bread": {
          "type": [
            "string",
            "null"
          ],
          "Describe": {
            "Title": "Sandwich Bot",
            "SubTitle": "Bread Picker"
          },
          "enum": [
            "NineGrainWheat",
            "NineGrainHoneyOat",
            "Italian",
            "ItalianHerbsAndCheese",
            "Flatbread"
          ]
        },
        "Cheese": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "American",
            "MontereyCheddar",
            "Pepperjack"
          ]
        },
        "Toppings": {
          "type": "array",
          "items": {
            "type": "integer",
            "enum": [
              "Everything",
              "Avocado",
              "BananaPeppers",
              "Cucumbers",
              "GreenBellPeppers",
              "Jalapenos",
              "Lettuce",
              "Olives",
              "Pickles",
              "RedOnion",
              "Spinach",
              "Tomatoes"
            ],
            "Values": {
              "Everything": { "Terms": [ "except", "but", "not", "no", "all", "everything" ] }
            }
          },
          "Validate": "var values = ((List<object>) value).OfType<string>(); var result = new ValidateResult {IsValid = true, Value = values} ; if (values != null && values.Contains(\"Everything\")) { result.Value = (from topping in new string[] {  \"Avocado\", \"BananaPeppers\", \"Cucumbers\", \"GreenBellPeppers\", \"Jalapenos\", \"Lettuce\", \"Olives\", \"Pickles\", \"RedOnion\", \"Spinach\", \"Tomatoes\"} where !values.Contains(topping) select topping).ToList();} return result;",
          "After": [ { "Message": [ "For sandwich toppings you have selected {Ingredients.Toppings}." ] } ]
        },
        "Sauces": {
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": "string",
            "enum": [
              "ChipotleSouthwest",
              "HoneyMustard",
              "LightMayonnaise",
              "RegularMayonnaise",
              "Mustard",
              "Oil",
              "Pepper",
              "Ranch",
              "SweetOnion",
              "Vinegar"
            ]
          }
        }
      }
    },
    "Specials": {
      "Templates": {
        "NoPreference": { "Patterns": [ "None" ] }
      },
      "type": [
        "string",
        "null"
      ],
      "Active": "return (string) state[\"Length\"] == \"FootLong\";",
      "Define": "field.SetType(null).AddDescription(\"cookie\", DynamicSandwich.FreeCookie).AddTerms(\"cookie\", Language.GenerateTerms(DynamicSandwich.FreeCookie, 2)).AddDescription(\"drink\", DynamicSandwich.FreeDrink).AddTerms(\"drink\", Language.GenerateTerms(DynamicSandwich.FreeDrink, 2)); return true;",
      "After": [ { "Confirm": "var cost = 0.0; switch ((string) state[\"Length\"]) { case \"SixInch\": cost = 5.0; break; case \"FootLong\": cost=6.50; break;} return new PromptAttribute($\"Total for your sandwich is {cost:C2} is that ok?\");" } ]
    },
    "DeliveryAddress": {
      "type": [
        "string",
        "null"
      ],
      "Validate": "var result = new ValidateResult{ IsValid = true, Value = value}; var address = (value as string).Trim(); if (address.Length > 0 && (address[0] < '0' || address[0] > '9')) {result.Feedback = DynamicSandwich.BadAddress; result.IsValid = false; } return result;"
    },
    "PhoneNumber": {
      "type": [ "string", "null" ],
      "pattern": "(\\(\\d{3}\\))?\\s*\\d{3}(-|\\s*)\\d{4}"
    },
    "DeliveryTime": {
      "Templates": {
        "StatusFormat": {
          "Patterns": [ "{&}: {:t}" ],
          "FieldCase": "None"
        }
      },
      "DateTime": true,
      "type": [
        "string",
        "null"
      ],
      "After": [ { "Confirm": [ "Do you want to order your {Length} {Sandwich} on {Ingredients.Bread} {&Ingredients.Bread} with {[{Ingredients.Cheese} {Ingredients.Toppings} {Ingredients.Sauces} to be sent to {DeliveryAddress} {?at {DeliveryTime}}?" ] } ]
    },
    "Rating": {
      "Describe": "your experience today",
      "type": [
        "number",
        "null"
      ],
      "minimum": 1,
      "maximum": 5,
      "After": [ { "Message": [ "Thanks for ordering your sandwich!" ] } ]
    }
  },
  "OnCompletion": "await context.PostAsync(\"We are currently processing your sandwich. We will message you the status.\");"
}

使用 JSON 架构实现 FormFlowImplement FormFlow with JSON schema

要使用 JSON 架构实现 FormFlow,请使用 FormBuilderJson,它支持与 FormBuilder 相同的流畅界面。To implement FormFlow with a JSON schema, use FormBuilderJson, which supports the same fluent interface as FormBuilder. 此代码示例演示如何实现使用 FormBuilder 自定义表单中所述的带批注的三明治机器人的 JSON 架构。This code example shows how to implement the JSON schema for the annotated sandwich bot that is described in Customize a form using FormBuilder.

public static IForm<JObject> BuildJsonForm()
{
    using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Microsoft.Bot.Sample.AnnotatedSandwichBot.AnnotatedSandwich.json"))
    {
        var schema = JObject.Parse(new StreamReader(stream).ReadToEnd());
        return new FormBuilderJson(schema)
            .AddRemainingFields()
            .Build();
    }
    ...
}

示例代码Sample code

有关演示如何使用 Bot Framework SDK for .NET 实现 FormFlow 的完整示例,请参阅 GitHub 中的多对话机器人示例Contoso Flowers 机器人示例For complete samples that show how to implement FormFlow using the Bot Framework SDK for .NET, see the Multi-Dialog Bot sample and the Contoso Flowers Bot sample in GitHub.

其他资源Additional resources