2017-06-14 6 views
1

StackOverflow Community!BotFrameworkのLUISでJSONシリアライザエラーが発生しました

私はチャットボットを持っており、よりスマートにするためにLUIS.aiを統合しました。会話の1つが上司(教師)と予約を予約しようとしています すべてがうまく機能していて、文字通り同じコードです。数時間前、私はいくつかの奇妙なエラーを経験しています。

Exception: Type 'Newtonsoft.Json.Linq.JArray' in Assembly 'Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' is not marked as serializable. 

エラーを再現するにはどうすればよいですか?

ユーザの入力にEntity(Teacher and Date)の両方が入力されていない場合は、FINEを使用してフォームが作成され、不足している入力を求め、提案された会議時間を提示します。

エンティティの1つが入力から欠落している場合、Formを作成し、欠落しているDateまたはTeacher Entityを尋ね、提案された会議時間を提示します。

しかし

、ユーザの入力は、両方のエンティティが含まれている場合:教師とあまりにも日付は、その後、私はエラーを取得しています。私はbuiltin.dateTimeV2のタイプであるユーザ発話からエンティティを取得しようとしていたときに私はこのエラーを経験しています

public static class WebApiConfig 
    { 
     public static void Register(HttpConfiguration config) 
     { 
      // Json settings 
      config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; 
      config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 
      config.Formatters.JsonFormatter.SerializerSettings.Formatting = Formatting.Indented; 
      JsonConvert.DefaultSettings =() => new JsonSerializerSettings() 
      { 
       ContractResolver = new CamelCasePropertyNamesContractResolver(), 
       Formatting = Newtonsoft.Json.Formatting.Indented, 
       NullValueHandling = NullValueHandling.Ignore, 
      }; 

      // Web API configuration and services 

      // Web API routes 
      config.MapHttpAttributeRoutes(); 

      config.Routes.MapHttpRoute(
       name: "DefaultApi", 
       routeTemplate: "api/{controller}/{id}", 
       defaults: new { id = RouteParameter.Optional } 
      ); 
     } 
    } 

は、ここに私のWebApiConfigクラスです。

この非同期メソッドが呼び出されます。フォームを構築するための

//From the LUIS.AI language model the entities 
    private const string EntityMeetingDate = "MeetingDate"; 
    private const string EntityTeacher = "Teacher"; 

    [LuisIntent("BookSupervision")] 
public async Task BookAppointment(IDialogContext context, IAwaitable<IMessageActivity> activity, LuisResult result) 
{ 
    var message = await activity; 
    await context.PostAsync($"I am analysing your message: '{message.Text}'..."); 

    var meetingsQuery = new MeetingsQuery(); 

    EntityRecommendation teacherEntityRecommendation; 
    EntityRecommendation dateEntityRecommendation; 

    if (result.TryFindEntity(EntityTeacher, out teacherEntityRecommendation)) 
    { 
     teacherEntityRecommendation.Type = "Name"; 
    } 
    if (result.TryFindEntity(EntityMeetingDate, out dateEntityRecommendation)) 
    { 
     dateEntityRecommendation.Type = "Date"; 
    } 

    var meetingsFormDialog = new FormDialog<MeetingsQuery>(meetingsQuery, this.BuildMeetingsForm, FormOptions.PromptInStart, result.Entities); 
    context.Call(meetingsFormDialog, this.ResumeAfterMeetingsFormDialog); 

} 

さらなる方法:

private IForm<MeetingsQuery> BuildMeetingsForm() 
{ 
    OnCompletionAsyncDelegate<MeetingsQuery> processMeetingsSearch = async (context, state) => 
    { 
     var message = "Searching for supervision slots"; 
     if (!string.IsNullOrEmpty(state.Date)) 
     { 
      message += $" at {state.Date}..."; 
     } 
     else if (!string.IsNullOrEmpty(state.Name)) 
     { 
      message += $" with professor {state.Name}..."; 
     } 
     await context.PostAsync(message); 
    }; 

    return new FormBuilder<MeetingsQuery>() 
     .Field(nameof(MeetingsQuery.Date), (state) => string.IsNullOrEmpty(state.Date)) 
     .Field(nameof(MeetingsQuery.Name), (state) => string.IsNullOrEmpty(state.Name)) 
     .OnCompletion(processMeetingsSearch) 
     .Build(); 
} 

private async Task ResumeAfterMeetingsFormDialog(IDialogContext context, IAwaitable<MeetingsQuery> result) 
{ 
try 
{ 
    var searchQuery = await result; 

    var meetings = await this.GetMeetingsAsync(searchQuery); 

    await context.PostAsync($"I found {meetings.Count()} available slots:"); 

    var resultMessage = context.MakeMessage(); 
    resultMessage.AttachmentLayout = AttachmentLayoutTypes.Carousel; 
    resultMessage.Attachments = new List<Attachment>(); 

    foreach (var meeting in meetings) 
    { 
     HeroCard heroCard = new HeroCard() 
     { 
      Title = meeting.Teacher, 
      Subtitle = meeting.Location, 
      Text = meeting.DateTime, 
      Images = new List<CardImage>() 
      { 
       new CardImage() {Url = meeting.Image} 
      }, 
      Buttons = new List<CardAction>() 
      { 
       new CardAction() 
       { 
        Title = "Book Appointment", 
        Type = ActionTypes.OpenUrl, 
        Value = $"https://www.bing.com/search?q=easj+roskilde+" + HttpUtility.UrlEncode(meeting.Location) 
       } 
      } 
     }; 

     resultMessage.Attachments.Add(heroCard.ToAttachment()); 
    } 

    await context.PostAsync(resultMessage); 
} 
catch (FormCanceledException ex) 
{ 
    string reply; 

    if (ex.InnerException == null) 
    { 
     reply = "You have canceled the operation."; 
    } 
    else 
    { 
     reply = $"Oops! Something went wrong :(Technical Details: {ex.InnerException.Message}"; 
    } 

    await context.PostAsync(reply); 
} 
finally 
{ 
    context.Wait(DeconstructionOfDialog); 
} 
} 


private async Task<IEnumerable<Meeting>> GetMeetingsAsync(MeetingsQuery searchQuery) 
{ 
    var meetings = new List<Meeting>(); 

    //some random result manually for demo purposes 
    for (int i = 1; i <= 5; i++) 
    { 
     var random = new Random(i); 
     Meeting meeting = new Meeting() 
     { 
      DateTime = $" Available time: {searchQuery.Date} At building {i}", 
      Teacher = $" Professor {searchQuery.Name}", 
      Location = $" Elisagårdsvej 3, Room {random.Next(1, 300)}", 
      Image = $"https://placeholdit.imgix.net/~text?txtsize=35&txt=Supervision+{i}&w=500&h=260" 
     }; 

     meetings.Add(meeting); 
    } 

    return meetings; 
} 

このコードが働いている、と私shoutoutと尊敬が上のコミュニティのために行くことに奇妙なこと私はこれが数多くのドキュメンテーションとサンプルを備えた素晴らしいプラットフォームだと思うので、GitHub。

答えて

4

これは既知の問題です(herehereも報告されています)。

かいつまんで、builtin.datetimeV2。*エンティティはまだBotBuilderではサポートされていないため、EntityRecommendationResolution辞書がタイプJArrayの値を持つエントリで終了。これらのエンティティをFormDialogに渡すと問題が発生します。エンティティはダイアログ内のプライベートフィールドなので、ほかのダイアログと同様にシリアル化されているため、NewtonsoftのクラスJArrayがシリアル化可能とマークされていないため、例外がスローされます。

datetimeV2エンティティのサポートを追加する要求はhereです。

私は今考えることができます回避策は、手動でのDateTimeエンティティの値を抽出し、それをあなたがそのresult.EntitiesコレクションからのDateTimeエンティティを除去することもFormDialogとに渡しているあなたのMeetingsQueryインスタンスのごDateフィールドを割り当てることですあなたはFormDialogに渡しています。

更新

あなたがthis Pull Requestで見ることができるように、これは、すでにSDKに固定されています。

+1

おかげさまで、私は何をして、エラーを解決しましたか?ヘルプ:@ejadib、子** builtin.dateTimeV2 **を持つMeetingDate複合エンティティを削除し、新しいカスタム(タイプ:シンプル)として追加しました。あなたの迅速な対応にもう一度感謝します!良い精神を維持してください! – ystvan

関連する問題