Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[For Discussion] Move JsonData to Core #31769

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8b410e8
Move JsonData to Core
annelo-msft Oct 12, 2022
e3113b4
update namespace to have JsonData side-by-side with JsonPatchDocument
annelo-msft Oct 12, 2022
40d53ed
Merge remote-tracking branch 'upstream/main' into annelo/core-jsondata
annelo-msft Oct 14, 2022
770fea4
move perf tests
annelo-msft Oct 14, 2022
5a0a54d
export APIs
annelo-msft Oct 14, 2022
7d308cb
Merge remote-tracking branch 'upstream/main' into annelo/core-jsondata
annelo-msft Oct 20, 2022
607d3f4
add some tests
annelo-msft Oct 21, 2022
ba8ce15
make castable from arbitrary type
annelo-msft Oct 21, 2022
73ba1f6
add DateTime cast test
annelo-msft Oct 21, 2022
f736db3
make internal members private and implement BindGetIndex
annelo-msft Oct 21, 2022
0f2f374
make jsonData internal; test introduces an issue with int equality th…
annelo-msft Oct 24, 2022
d0b4e07
tidyup
annelo-msft Oct 24, 2022
abe7c77
Merge remote-tracking branch 'upstream/main' into annelo/core-jsondata
annelo-msft Oct 24, 2022
bf207c7
refactoring and calling cast operators dynamically
annelo-msft Oct 24, 2022
8ebad75
add test project to test only public API; implement BindBinaryOperation
annelo-msft Oct 24, 2022
52c5123
add more public tests; string equality still fails when dynamic objec…
annelo-msft Oct 24, 2022
3958786
Merge remote-tracking branch 'upstream/main' into annelo/core-jsondata
annelo-msft Oct 25, 2022
562b773
move 'special array property' logic into BindGetMember
annelo-msft Oct 26, 2022
0856479
make JsonData public; update CLU sample with JsonData
annelo-msft Oct 28, 2022
5167a1f
ignore case when looking up property; add ToString() for number type.
annelo-msft Nov 1, 2022
d2b7d71
return null for optional properties
annelo-msft Nov 1, 2022
7e5408d
continuing to port CLI samples.
annelo-msft Nov 1, 2022
e19af63
move samples to JsonData
annelo-msft Nov 1, 2022
64ef81a
update snippets
annelo-msft Nov 1, 2022
9496dbe
Merge remote-tracking branch 'upstream/main' into annelo/core-jsondata
annelo-msft Nov 1, 2022
146bcc8
illustrate more samples with JsonData
annelo-msft Nov 1, 2022
0aca600
bug fix
annelo-msft Nov 2, 2022
d84bdd3
add tests for cases found during samples update
annelo-msft Nov 2, 2022
8118f74
Merge remote-tracking branch 'upstream/main' into annelo/core-jsondata
annelo-msft Nov 11, 2022
795e2ff
Dispose JsonDocument
annelo-msft Nov 11, 2022
a0fadb7
Merge remote-tracking branch 'upstream/main' into annelo/core-jsondata
annelo-msft Nov 14, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 49 additions & 54 deletions sdk/cognitivelanguage/Azure.AI.Language.Conversations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,39 +162,38 @@ var data = new

Response response = client.AnalyzeConversation(RequestContent.Create(data));

using JsonDocument result = JsonDocument.Parse(response.ContentStream);
JsonElement conversationalTaskResult = result.RootElement;
JsonElement conversationPrediction = conversationalTaskResult.GetProperty("result").GetProperty("prediction");
var json = response.Content.ToDynamic();
var conversationPrediction = json.Result.Prediction;

Console.WriteLine($"Top intent: {conversationPrediction.GetProperty("topIntent").GetString()}");
Console.WriteLine($"Top intent: {conversationPrediction.TopIntent}");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed with @KrzysztofCwalina offline, but I don't think we should automatically convert camelCase JSON properties to PascalCase .NET properties on responses. Requests don't get the same treatment, so this may be confusing or even misleading. Say you get a response back, want to update it, and then send it back (which you also can't since JsonData is effectively immutable):

var json = response.Content.ToDynamic();
var data = new
{
  Id = json.Id,
  Foo = "new foo",
};
client.UpdateFoo(Request.Create(data)); // throws RequestFailedException: 400 BadParameter or something because the properties are supposed to be camelCase.

I appreciate we want to be idiomatic, but as soon as customers are having to deal with raw JSON - via System.Text.Json like my samples were before vs. what you're prototyping here with JsonData (which is a remarkable improvement) - I don't think we should "auto-correct" anything. Python nor JS would since customers are working directly with the JSON data. I don't think C# / .NET should either.

Model classes give us this ability, and once we generate them (for Cadl or otherwise) we can and should do that translation because we can do so consistently.

/cc @tg-msft

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I don't understand the thinking there. We do this in our public models, and the idea is that JsonData is a stand-in until we add those types. Ideally, the customer would have to change very little to move to any types we added to a library. It's not that they're dealing with raw Json (which they can do easily if they want) -- it's a layer over the Json (or Xml, or whatever) that makes it conform to a higher .NET standard for look-and-feel. Is consistency with anonymous types your primary concern here, because I agree that is not good. Are there any other considerations I'm not thinking of?

Copy link
Member Author

@annelo-msft annelo-msft Nov 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see that this is a question about round-tripping the type, my apologies for having missed that the first time. We are planning to provide a separate API to handle-round tripping, that may be able to address this. I am still curious to know if there are other considerations here beyond the inconsistency across input/output that we should also be aware of.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assume with my example above that the JSON schema is indeed camelCase, as most services define (and should): the request would accept id and foo, not Id and Foo. However, by translating from camelCase to PascalCase we could give callers the impression that the properties are indeed Id and Foo.

This isn't just about roundtripping, though. It's about perception. If all the response properties are PascalCase, why wouldn't many think that request properties are too?

I appreciate this isn't "raw" JSON. That's not what I intended. But it's a very thin wrapper over raw JSON that is meant to provide a JSON-like interaction for the customer, yes? By morphing into something it's not just to seem idiomatic, we create this confusion of casing for customers. Why not just leave it with the exact shape - casing and all - as the service returns (response) and expects (request)?

Copy link
Member Author

@annelo-msft annelo-msft Nov 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's totally fair - all good points. It feels like the question hinges on how thin the wrapper is and how well we document and illustrate via samples what the type is actually doing. If, for example, it also wraps other formats like XML, it might be more clear that you can't make too many assumptions about what's underneath.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this supports XML, I don't see my point changing: if an XML document uses camelCase or PascalCase (and in my experience it varies even more than with JSON, which is more often camelCase), we should leave casing as is to avoid confusion. If we start showing that customers can always use PascalCase for responses, why wouldn't they think they can use it for input as well? Or if they use the obj["foo"]["bar"] pattern it will also vary from obj.Foo.Bar. Changing cases like that just seems so jarring.

What benefit to the customer does translating the casing have? I can certainly see a lot of cons. The only pro is "it feels like C#", but they aren't working with generated types (C# or otherwise): they are working with thin wrappers over raw JSON, XML, etc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should ToDynamic take an optional ObjectSerailizer so folks can customize this? I feel like that would easily allow this to work for people who wanted it, but then we could get away with less magic by default if we didn't change the case.


Console.WriteLine("Intents:");
foreach (JsonElement intent in conversationPrediction.GetProperty("intents").EnumerateArray())
foreach (var intent in conversationPrediction.Intents)
{
Console.WriteLine($"Category: {intent.GetProperty("category").GetString()}");
Console.WriteLine($"Confidence: {intent.GetProperty("confidenceScore").GetSingle()}");
Console.WriteLine($" Category: {intent.Category}");
Console.WriteLine($" Confidence: {intent.ConfidenceScore}");
Console.WriteLine();
}

Console.WriteLine("Entities:");
foreach (JsonElement entity in conversationPrediction.GetProperty("entities").EnumerateArray())
foreach (var entity in conversationPrediction.Entities)
{
Console.WriteLine($"Category: {entity.GetProperty("category").GetString()}");
Console.WriteLine($"Text: {entity.GetProperty("text").GetString()}");
Console.WriteLine($"Offset: {entity.GetProperty("offset").GetInt32()}");
Console.WriteLine($"Length: {entity.GetProperty("length").GetInt32()}");
Console.WriteLine($"Confidence: {entity.GetProperty("confidenceScore").GetSingle()}");
Console.WriteLine($" Category: {entity.Category}");
Console.WriteLine($" Text: {entity.Text}");
Console.WriteLine($" Offset: {entity.Offset}");
Console.WriteLine($" Length: {entity.Length}");
Console.WriteLine($" Confidence: {entity.ConfidenceScore}");
Console.WriteLine();

if (entity.TryGetProperty("resolutions", out JsonElement resolutions))
if (entity.Resolutions != null)
{
foreach (JsonElement resolution in resolutions.EnumerateArray())
foreach (var resolution in entity.Resolutions)
{
if (resolution.GetProperty("resolutionKind").GetString() == "DateTimeResolution")
if (resolution.ResolutionKind == "DateTimeResolution")
{
Console.WriteLine($"Datetime Sub Kind: {resolution.GetProperty("dateTimeSubKind").GetString()}");
Console.WriteLine($"Timex: {resolution.GetProperty("timex").GetString()}");
Console.WriteLine($"Value: {resolution.GetProperty("value").GetString()}");
Console.WriteLine($"Datetime Sub Kind: {resolution.DateTimeSubKind}");
Console.WriteLine($"Timex: {resolution.Timex}");
Console.WriteLine($"Value: {resolution.Value}");
Console.WriteLine();
}
}
Expand Down Expand Up @@ -302,28 +301,26 @@ var data = new

Response response = client.AnalyzeConversation(RequestContent.Create(data));

using JsonDocument result = JsonDocument.Parse(response.ContentStream);
JsonElement conversationalTaskResult = result.RootElement;
JsonElement orchestrationPrediction = conversationalTaskResult.GetProperty("result").GetProperty("prediction");
var conversationalTaskResult = response.Content.ToDynamic();
var orchestrationPrediction = conversationalTaskResult.Result.Prediction;
```

#### Question Answering prediction

If your conversation was analyzed by Question Answering, it will include an intent - perhaps even the top intent - from which you can retrieve answers:

```C# Snippet:ConversationAnalysis_AnalyzeConversationOrchestrationPredictionQnA
string respondingProjectName = orchestrationPrediction.GetProperty("topIntent").GetString();
JsonElement targetIntentResult = orchestrationPrediction.GetProperty("intents").GetProperty(respondingProjectName);

if (targetIntentResult.GetProperty("targetProjectKind").GetString() == "QuestionAnswering")
string respondingProjectName = orchestrationPrediction.TopIntent;
var targetIntentResult = orchestrationPrediction.Intents[respondingProjectName];
if (targetIntentResult.TargetProjectKind == "QuestionAnswering")
{
Console.WriteLine($"Top intent: {respondingProjectName}");

JsonElement questionAnsweringResponse = targetIntentResult.GetProperty("result");
var questionAnsweringResponse = targetIntentResult.Result;
Console.WriteLine($"Question Answering Response:");
foreach (JsonElement answer in questionAnsweringResponse.GetProperty("answers").EnumerateArray())
foreach (var answer in questionAnsweringResponse.Answers)
{
Console.WriteLine(answer.GetProperty("answer").GetString());
Console.WriteLine(answer.Answer);
}
}
```
Expand Down Expand Up @@ -402,20 +399,19 @@ var data = new

Operation<BinaryData> analyzeConversationOperation = client.AnalyzeConversation(WaitUntil.Completed, RequestContent.Create(data));

using JsonDocument result = JsonDocument.Parse(analyzeConversationOperation.Value.ToStream());
JsonElement jobResults = result.RootElement;
foreach (JsonElement task in jobResults.GetProperty("tasks").GetProperty("items").EnumerateArray())
var jobResults = analyzeConversationOperation.Value.ToDynamic();
foreach (var task in jobResults.Tasks.Items)
{
Console.WriteLine($"Task name: {task.GetProperty("taskName").GetString()}");
JsonElement results = task.GetProperty("results");
foreach (JsonElement conversation in results.GetProperty("conversations").EnumerateArray())
Console.WriteLine($"Task name: {task.TaskName}");
var results = task.Results;
foreach (var conversation in results.Conversations)
{
Console.WriteLine($"Conversation: #{conversation.GetProperty("id").GetString()}");
Console.WriteLine($"Conversation: #{conversation.Id}");
Console.WriteLine("Summaries:");
foreach (JsonElement summary in conversation.GetProperty("summaries").EnumerateArray())
foreach (var summary in conversation.Summaries)
{
Console.WriteLine($"Text: {summary.GetProperty("text").GetString()}");
Console.WriteLine($"Aspect: {summary.GetProperty("aspect").GetString()}");
Console.WriteLine($"Text: {summary.Text}");
Console.WriteLine($"Aspect: {summary.Aspect}");
}
Console.WriteLine();
}
Expand Down Expand Up @@ -484,31 +480,30 @@ var data = new

Operation<BinaryData> analyzeConversationOperation = client.AnalyzeConversation(WaitUntil.Completed, RequestContent.Create(data));

using JsonDocument result = JsonDocument.Parse(analyzeConversationOperation.Value.ToStream());
JsonElement jobResults = result.RootElement;
foreach (JsonElement task in jobResults.GetProperty("tasks").GetProperty("items").EnumerateArray())
var jobResults = analyzeConversationOperation.Value.ToDynamic();
foreach (var task in jobResults.Tasks.Items)
{
JsonElement results = task.GetProperty("results");
var results = task.Results;

Console.WriteLine("Conversations:");
foreach (JsonElement conversation in results.GetProperty("conversations").EnumerateArray())
foreach (var conversation in results.Conversations)
{
Console.WriteLine($"Conversation: #{conversation.GetProperty("id").GetString()}");
Console.WriteLine($"Conversation: #{conversation.Id}");
Console.WriteLine("Conversation Items:");
foreach (JsonElement conversationItem in conversation.GetProperty("conversationItems").EnumerateArray())
foreach (var conversationItem in conversation.ConversationItems)
{
Console.WriteLine($"Conversation Item: #{conversationItem.GetProperty("id").GetString()}");
Console.WriteLine($"Conversation Item: #{conversationItem.Id}");

Console.WriteLine($"Redacted Text: {conversationItem.GetProperty("redactedContent").GetProperty("text").GetString()}");
Console.WriteLine($"Redacted Text: {conversationItem.RedactedContent.Text}");

Console.WriteLine("Entities:");
foreach (JsonElement entity in conversationItem.GetProperty("entities").EnumerateArray())
foreach (var entity in conversationItem.Entities)
{
Console.WriteLine($"Text: {entity.GetProperty("text").GetString()}");
Console.WriteLine($"Offset: {entity.GetProperty("offset").GetInt32()}");
Console.WriteLine($"Category: {entity.GetProperty("category").GetString()}");
Console.WriteLine($"Confidence Score: {entity.GetProperty("confidenceScore").GetSingle()}");
Console.WriteLine($"Length: {entity.GetProperty("length").GetInt32()}");
Console.WriteLine($"Text: {entity.Text}");
Console.WriteLine($"Offset: {entity.Offset}");
Console.WriteLine($"Category: {entity.Category}");
Console.WriteLine($"Confidence Score: {entity.ConfidenceScore}");
Console.WriteLine($"Length: {entity.Length}");
Console.WriteLine();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,39 +43,38 @@ var data = new

Response response = client.AnalyzeConversation(RequestContent.Create(data));

using JsonDocument result = JsonDocument.Parse(response.ContentStream);
JsonElement conversationalTaskResult = result.RootElement;
JsonElement conversationPrediction = conversationalTaskResult.GetProperty("result").GetProperty("prediction");
var json = response.Content.ToDynamic();
var conversationPrediction = json.Result.Prediction;

Console.WriteLine($"Top intent: {conversationPrediction.GetProperty("topIntent").GetString()}");
Console.WriteLine($"Top intent: {conversationPrediction.TopIntent}");

Console.WriteLine("Intents:");
foreach (JsonElement intent in conversationPrediction.GetProperty("intents").EnumerateArray())
foreach (var intent in conversationPrediction.Intents)
{
Console.WriteLine($"Category: {intent.GetProperty("category").GetString()}");
Console.WriteLine($"Confidence: {intent.GetProperty("confidenceScore").GetSingle()}");
Console.WriteLine($" Category: {intent.Category}");
Console.WriteLine($" Confidence: {intent.ConfidenceScore}");
Console.WriteLine();
}

Console.WriteLine("Entities:");
foreach (JsonElement entity in conversationPrediction.GetProperty("entities").EnumerateArray())
foreach (var entity in conversationPrediction.Entities)
{
Console.WriteLine($"Category: {entity.GetProperty("category").GetString()}");
Console.WriteLine($"Text: {entity.GetProperty("text").GetString()}");
Console.WriteLine($"Offset: {entity.GetProperty("offset").GetInt32()}");
Console.WriteLine($"Length: {entity.GetProperty("length").GetInt32()}");
Console.WriteLine($"Confidence: {entity.GetProperty("confidenceScore").GetSingle()}");
Console.WriteLine($" Category: {entity.Category}");
Console.WriteLine($" Text: {entity.Text}");
Console.WriteLine($" Offset: {entity.Offset}");
Console.WriteLine($" Length: {entity.Length}");
Console.WriteLine($" Confidence: {entity.ConfidenceScore}");
Console.WriteLine();

if (entity.TryGetProperty("resolutions", out JsonElement resolutions))
if (entity.Resolutions != null)
{
foreach (JsonElement resolution in resolutions.EnumerateArray())
foreach (var resolution in entity.Resolutions)
{
if (resolution.GetProperty("resolutionKind").GetString() == "DateTimeResolution")
if (resolution.ResolutionKind == "DateTimeResolution")
{
Console.WriteLine($"Datetime Sub Kind: {resolution.GetProperty("dateTimeSubKind").GetString()}");
Console.WriteLine($"Timex: {resolution.GetProperty("timex").GetString()}");
Console.WriteLine($"Value: {resolution.GetProperty("value").GetString()}");
Console.WriteLine($"Datetime Sub Kind: {resolution.DateTimeSubKind}");
Console.WriteLine($"Timex: {resolution.Timex}");
Console.WriteLine($"Value: {resolution.Value}");
Console.WriteLine();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ var data = new

Response response = client.AnalyzeConversation(RequestContent.Create(data));

using JsonDocument result = JsonDocument.Parse(response.ContentStream);
JsonElement conversationalTaskResult = result.RootElement;
JsonElement orchestrationPrediction = conversationalTaskResult.GetProperty("result").GetProperty("prediction");
var conversationalTaskResult = response.Content.ToDynamic();
var orchestrationPrediction = conversationalTaskResult.Result.Prediction;
```

## Asynchronous
Expand All @@ -55,9 +54,8 @@ Using the same `data` definition above, you can make an asynchronous request by
```C# Snippet:ConversationAnalysis_AnalyzeConversationOrchestrationPredictionAsync
Response response = await client.AnalyzeConversationAsync(RequestContent.Create(data));

using JsonDocument result = await JsonDocument.ParseAsync(response.ContentStream);
JsonElement conversationalTaskResult = result.RootElement;
JsonElement orchestrationPrediction = conversationalTaskResult.GetProperty("result").GetProperty("prediction");
var conversationalTaskResult = response.Content.ToDynamic();
var orchestrationPrediction = conversationalTaskResult.Result.Prediction;
```

## Accessing project specific results
Expand All @@ -67,61 +65,60 @@ Depending on the project chosen by your orchestration model, you may get results
### Question Answering

```C# Snippet:ConversationAnalysis_AnalyzeConversationOrchestrationPredictionQnA
string respondingProjectName = orchestrationPrediction.GetProperty("topIntent").GetString();
JsonElement targetIntentResult = orchestrationPrediction.GetProperty("intents").GetProperty(respondingProjectName);

if (targetIntentResult.GetProperty("targetProjectKind").GetString() == "QuestionAnswering")
string respondingProjectName = orchestrationPrediction.TopIntent;
var targetIntentResult = orchestrationPrediction.Intents[respondingProjectName];
if (targetIntentResult.TargetProjectKind == "QuestionAnswering")
{
Console.WriteLine($"Top intent: {respondingProjectName}");

JsonElement questionAnsweringResponse = targetIntentResult.GetProperty("result");
var questionAnsweringResponse = targetIntentResult.Result;
Console.WriteLine($"Question Answering Response:");
foreach (JsonElement answer in questionAnsweringResponse.GetProperty("answers").EnumerateArray())
foreach (var answer in questionAnsweringResponse.Answers)
{
Console.WriteLine(answer.GetProperty("answer").GetString());
Console.WriteLine(answer.Answer);
}
}
```

### Conversation

```C# Snippet:ConversationAnalysis_AnalyzeConversationOrchestrationPredictionConversation
string respondingProjectName = orchestrationPrediction.GetProperty("topIntent").GetString();
JsonElement targetIntentResult = orchestrationPrediction.GetProperty("intents").GetProperty(respondingProjectName);
string respondingProjectName = orchestrationPrediction.TopIntent;
var targetIntentResult = orchestrationPrediction.Intents[respondingProjectName];

if (targetIntentResult.GetProperty("targetProjectKind").GetString() == "Conversation")
if (targetIntentResult.TargetProjectKind == "Conversation")
{
JsonElement conversationResult = targetIntentResult.GetProperty("result");
JsonElement conversationPrediction = conversationResult.GetProperty("prediction");
var conversationResult = targetIntentResult.Result;
var conversationPrediction = conversationResult.Prediction;

Console.WriteLine($"Top Intent: {conversationPrediction.GetProperty("topIntent").GetString()}");
Console.WriteLine($"Top Intent: {conversationPrediction.TopIntent}");
Console.WriteLine($"Intents:");
foreach (JsonElement intent in conversationPrediction.GetProperty("intents").EnumerateArray())
foreach (var intent in conversationPrediction.Intents)
{
Console.WriteLine($"Intent Category: {intent.GetProperty("category").GetString()}");
Console.WriteLine($"Confidence: {intent.GetProperty("confidenceScore").GetSingle()}");
Console.WriteLine($"Intent Category: {intent.Category}");
Console.WriteLine($"Confidence: {intent.ConfidenceScore}");
Console.WriteLine();
}

Console.WriteLine($"Entities:");
foreach (JsonElement entity in conversationPrediction.GetProperty("entities").EnumerateArray())
foreach (var entity in conversationPrediction.Entities)
{
Console.WriteLine($"Entity Text: {entity.GetProperty("text").GetString()}");
Console.WriteLine($"Entity Category: {entity.GetProperty("category").GetString()}");
Console.WriteLine($"Confidence: {entity.GetProperty("confidenceScore").GetSingle()}");
Console.WriteLine($"Starting Position: {entity.GetProperty("offset").GetInt32()}");
Console.WriteLine($"Length: {entity.GetProperty("length").GetInt32()}");
Console.WriteLine($"Entity Text: {entity.Text}");
Console.WriteLine($"Entity Category: {entity.Category}");
Console.WriteLine($"Confidence: {entity.ConfidenceScore}");
Console.WriteLine($"Starting Position: {entity.Offset}");
Console.WriteLine($"Length: {entity.Length}");
Console.WriteLine();

if (entity.TryGetProperty("resolutions", out JsonElement resolutions))
if (entity.Resolutions != null)
{
foreach (JsonElement resolution in resolutions.EnumerateArray())
foreach (var resolution in entity.Resolutions)
{
if (resolution.GetProperty("resolutionKind").GetString() == "DateTimeResolution")
if (resolution.ResolutionKind == "DateTimeResolution")
{
Console.WriteLine($"Datetime Sub Kind: {resolution.GetProperty("dateTimeSubKind").GetString()}");
Console.WriteLine($"Timex: {resolution.GetProperty("timex").GetString()}");
Console.WriteLine($"Value: {resolution.GetProperty("value").GetString()}");
Console.WriteLine($"Datetime Sub Kind: {resolution.DateTimeSubKind}");
Console.WriteLine($"Timex: {resolution.Timex}");
Console.WriteLine($"Value: {resolution.Value}");
Console.WriteLine();
}
}
Expand All @@ -133,12 +130,12 @@ if (targetIntentResult.GetProperty("targetProjectKind").GetString() == "Conversa
### LUIS

```C# Snippet:ConversationAnalysis_AnalyzeConversationOrchestrationPredictionLuis
string respondingProjectName = orchestrationPrediction.GetProperty("topIntent").GetString();
JsonElement targetIntentResult = orchestrationPrediction.GetProperty("intents").GetProperty(respondingProjectName);
string respondingProjectName = orchestrationPrediction.TopIntent;
var targetIntentResult = orchestrationPrediction.Intents[respondingProjectName];

if (targetIntentResult.GetProperty("targetProjectKind").GetString() == "Luis")
if (targetIntentResult.TargetProjectKind == "Luis")
{
JsonElement luisResponse = targetIntentResult.GetProperty("result");
Console.WriteLine($"LUIS Response: {luisResponse.GetRawText()}");
var luisResponse = targetIntentResult.Result;
Console.WriteLine($"LUIS Response: {(string)luisResponse}");
}
```
Loading